EntityFramework 6 Миграции для существующих и новых баз данных?

В нашем программном обеспечении у нас есть клиентская база с существующими базами данных. В настоящее время доступ к базам данных осуществляется через EntitySpaces, но мы бы хотели перейти на EntityFramework (v6), так как EntitySpaces больше не поддерживается. Мы также хотели бы использовать функцию миграции. Автоматические миграции отключены, поскольку мы хотим разрешить миграцию базы данных только администратору.

Мы сгенерировали модель EF из существующей базы данных. Все это работает довольно хорошо, но реальная проблема, с которой мы сталкиваемся, заключается в программном различении существующих баз данных, соответствующих модели, но еще не преобразованных в EF (отсутствует таблица MigrationsHistory), и пустых / новых баз данных. Преобразование существующих баз данных хорошо работает с пустой миграцией, но для новых баз данных нам также нужна миграция, содержащая полную модель. Первоначальная миграция в цепочке миграции всегда конфликтует с существующими базами данных. Конечно, мы могли бы создать обходной путь с помощью внешних сценариев SQL или команд ADO, создав и заполнив таблицу MigrationsHistory. Но это то, чего мы хотели бы избежать, потому что некоторые из наших клиентов используют базы данных MsSql, другие - Oracle. Поэтому нам бы очень хотелось сохранить уровень абстракции, предоставляемый EF.

Есть ли способ заставить EF обрабатывать как существующие, так и новые базы данных посредством миграции на основе кода, не прибегая к обходным решениям, не относящимся к EF?

1 ответ

Решение

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

Простейшим методом продолжения будет использование метода Seed для создания исходной базы данных, если ее нет. Сделать это...

  1. Начиная с пустой базы данных, добавьте миграцию Initial Create и получите сгенерированный SQL

    Add-Migration InitialCreate
    Update-Database -Script
    
  2. Сохраните этот скрипт. Вы можете добавить его в ресурс, статический файл или даже оставить его встроенным в коде, если вы действительно этого хотите, это ваше дело.

  3. Удалите весь код из миграции InitialCreate (оставив его с пустыми функциями Up() и Down()). Это позволит выполнить вашу пустую миграцию, в результате чего будет сгенерирована таблица MigrationHistory.

  4. В вашем классе конфигурации миграции вы можете запрашивать и выполнять SQL динамически, используя context.Database.SqlQuery а также context.Database.ExecuteSqlCommand, Проверьте наличие основных таблиц и, если они отсутствуют, выполните сценарий, сгенерированный выше.

Это не очень аккуратно, но просто реализовать. Проверьте это хорошо, так как метод Seed запускается после КАЖДОЙ миграции, а не только начальной. Вот почему вам нужно проверить наличие основной таблицы, прежде чем что-либо делать.

Более сложный подход заключается в написании метода "CreateTableIfNotExists" для миграций, но это будет включать использование Reflection для вызова внутренних методов в классе DbMigration.

Другие вопросы по тегам