Как удалить все данные без нарушения ссылочной целостности с помощью Doctrine? - PullRequest
5 голосов
/ 14 августа 2011

Я собрал плагин для модульного тестирования для Symfony 1.4 , который пытается автоматически управлять базой данных, аналогично тому, как это делает инфраструктура тестирования Django (уничтожать и перестраивать базу данных между тестами).

Имеет смысл уничтожить и перестроить базу данных до первого запуска теста, поскольку схема могла измениться во время разработки, и было бы просто ужасно садистски заставить разработчика синхронизировать свою тестовую базу данных со своими моделями.вручную.

Однако после первого запуска теста я обнаружил, что обычно быстрее просто удалить все данные, что было бы довольно простой задачей, за исключением проблемы внешних ключей, которая требует, чтобыданные должны быть удалены в правильном порядке.

Для MySQL это не проблема;просто SET FOREIGN_KEY_CHECKS = 0, и вы можете разрушить ссылочную целостность для вашего сердца (конечно, до тех пор, пока не придет время SET FOREIGN_KEY_CHECKS = 1, но в этом случае не останется никаких данных, поэтому MySQL не на что жаловаться).

Но это работает только до тех пор, пока тестовая база данных использует MySQL.Для любой другой СУБД (особенно Sqlite) это с треском провалится.

Предоставляет ли Doctrine 1.2 средство для удаления всех данных в каждой таблице или есть способ «следовать» отношениям (т. Е. Определить, какиетаблицы имеют внешние ключи и сначала удаляются из них)?

Ответы [ 3 ]

2 голосов
/ 14 августа 2011

Я бы использовал Doctrine DBAL и сначала нашел бы внешние ключи. Просмотрите документацию DBAL от Doctrine о Schema-Manager , связанной с ним документации API , а также о методах, представленных в ForeignKeyConstraint .

EDIT : для доктрины 1.2, похоже, существует аналогичный способ получения внешних ключей, документированных здесь .

Найти все ограничения внешнего ключа и на основе этих ограничений разрешить коду решить, в каком порядке можно удалить данные.

0 голосов
/ 11 августа 2013

Альтернативный (хотя и не совсем тривиальный) подход заключается в использовании транзакций.

Начните транзакцию в начале теста, а затем выполните откат после его завершения.База данных удалит все данные, созданные во время теста.

Однако необходимо позаботиться о том, чтобы проверенный код, который фактически основан на транзакциях, продолжал работать.

Этоспособ работы тестовой среды Джанго :

class TestCase(TransactionTestCase):
    """
    Does basically the same as TransactionTestCase, but surrounds every test
    with a transaction, monkey-patches the real transaction management routines to
    do nothing, and rollsback the test transaction at the end of the test. You have
    to use TransactionTestCase, if you need transaction management inside a test.
    """
0 голосов
/ 14 августа 2011

Doctrine_Data->purge() использует Doctrine_Connection_UnitOfWork->buildFlushTree(), чтобы сделать именно то, что я пытаюсь сделать.

В некотором смысле имеет смысл, поскольку Doctrine_Data_Import->doImport() (т.е. symfony doctrine:data-load) уже обеспечивает функциональность, которую я пытаюсь изобрести ... как я пропустил эту? : P

...