Почему для этапа добавления-миграции EF Migrations в Entity Framework требуется строка подключения к базе данных?

Я пытаюсь использовать и понимать EF Migrations (используя EF 4.3.1, Code First). Чтобы создать новое изменение, я должен использовать такую команду:

Add-Migration MyMigration
   -ConnectionString "Data Source=.;Initial Catalog=mydb;" 
   -ConnectionProviderName "System.Data.SqlClient"
   -StartUpProjectName MyWebsite 
   -ProjectName MyEF.Migrations

Почему Add-Migration требует данные строки подключения?Update-Database нужен тот, который имеет смысл. Но разве у Add-Migration нет всего, что нужно, от DbContext и Конфигурации?

Это не просто пустое чудо, это очень запутанно, чтобы дать ему базу данных, потому что у нас есть «многопользовательский режим». вещь, где требуемая база данных является гибкой и может меняться от запроса к запросу, не говоря уже о статической компиляции. Так что еслиAdd-Migration на самом деле использует эту базу данных для чего-либо, у нас есть проблема.

ОБНОВЛЕНИЕ: Мы отказались от EF Migrations и используемСвободный Мигратор вместо этого и счастливы. Это намного, намного быстрее, даже если учесть тот факт, что нам нужно написать несколько вещей дважды (один раз для объекта EF и один раз для миграции), и у него нет проблем, обсуждаемых в этом вопросе.

Ответы на вопрос(4)

Я смотрел это видео Роуэн Миллер с марта 2014 года:Миграции - под капотом

В видео Роуэн объясняет, чтоAdd-Migration Команда выполняет несколько шагов, которые включают в себя компонент под названиемEdmModelDiffer. The EdmModelDiffer сравнивает текущую модель с предыдущей моделью из последней миграции (которая встроена в файл resx предыдущей миграции) и затем вычисляет необходимые изменения в базе данных.

ИтакEdmModelDiffer Компонент требует подключения к базе данных.

Шаги, описанные в видео:

  1. Build current model from code
  2. Get previous model from last migration (stored as snapshot in resx file)
  3. Calculate required database changes (done by the EdmModelDiffer)
  4. Generated the new migration file

Теоретически можно предположить, что было бы достаточно сравнить эту текущую модель с моделью последней миграции, чтобы сгенерировать новую миграцию. Но в то же время другие люди могли внести изменения в базу данных тоже. Вероятно, поэтому существует также проверка базы данных. Без этого результирующий файл миграции не должен быть корректным.


Взгляните также на второе видео под названиемМиграции - командная среда

ОП написал:

But doesn't Add-Migration have everything it needs from the DbContext and the Configuration?

Нет - как уже упоминалось здесь, часть кода Designer для ручной миграции (созданнаяadd-migration) содержит снимок вашей схемы базы данных.

Тем не менее, тот факт, что вы используете строку подключения и т. Д., Очень странный. EF обычно подразумевает это из вашего класса (ов) DbContext и Web.Config. В проекте, где у меня есть одна база данных и один DbContext, я создаю класс Configuration и добавляю миграцию вручную с помощью:

add-migration

Мне не нужно передавать какие-либо другие аргументы командной строки. Это в EF 4.3.1 - возможно, вы использовали CTP или какую-то более старую версию или просто неправильно поняли документы?

Если у меня есть несколько БД или DbContexts, то у меня есть несколько классов конфигурации и я использую, например:

add-migration -conf Log

Который использует мой класс конфигурации и связанную строку подключения в Web.config, чтобы добавить миграцию вручную для этой базы данных / DbContext.

Вот более длинный пример кода простого DbContext, предназначенного для хранения журналов (отдельно от основной базы данных):

namespace MyProj.Models.Log
{
    public class LogDb : DbContext
    {
        public DbSet<LogLine> LogLines { get; set; }
        public DbSet<LogTag> LogTags { get; set; }


        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }

    public LogDb()
#if DEPLOYDB
         : base("LogDeploy")
#else
         : base()
#endif
     {
     }
}

namespace MyProj.Migrations
{
    internal sealed class Log : DbMigrationsConfiguration<LogDb>
    {
        public Log()
        {
            AutomaticMigrationsEnabled = true;
        }
    }
}

В Web.Config:

<add name="LogDb" connectionString="Initial Catalog=Log;Data Source=.\SqlExpress;Integrated Security=SSPI;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />
<add name="LogDeploy" connectionString="Initial Catalog=Log;Data Source=00.00.000.00,12345;User ID=sql;Password=xxx;Network Library=DBMSSOCN" providerName="System.Data.SqlClient" />

Так что в этом примере у меня есть несколько баз данных, несколько DbContexts. LogDb использует другую строку подключения в Web.Config в зависимости от того, является ли «DBDEPLOY» quot; определяется во время компиляции; если это так, он использует & quot; LogDeploy. & quot; Если нет, используется значение по умолчанию - строка подключения с тем же именем, что и у класса, & quot; LogDb. & Quot; Это позволяет мне легко развертывать изменения БД на сервере с моего локального компьютера, переключая конфигурацию проекта, открывая порт на компьютере с базой данных SQL и выполняя:

> update-database -conf Log

в консоли диспетчера пакетов.

Мне стало любопытно, когда я прочитал ваш вопрос, поэтому я запустил Sql Server Profiler, чтобы посмотреть, что происходит при запуске add -igration. Он действительно подключается к базе данных и обращается к базе данных, чтобы проверить__MigrationHistory Таблица.

Это также показано в сообщении об ошибке, возникающем при попытке создать вторую миграцию на основе кода без запуска первой:

Unable to generate an explicit migration because the following explicit migrations are pending: [201205291928386_foo]. Apply the pending explicit migrations before attempting to generate a new explicit migration.

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

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

Edit

Как указывает @Ladislav Mrnka, проверка с базой данных необходима, если смешиваются основанные на коде и автоматические миграции. Когда вы создаете новую миграцию, она должна включать все, что изменилось в вашей модели с момента последней миграции. Если вы используете автоматическую миграцию, она не отслеживается в коде. При расчете изменений, которые необходимо включить в миграцию, в качестве основы используется последний запуск миграции. Единственный способ проверить это - база данных - поскольку автоматические миграции могут быть включены.

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

Add-Migration проверяет наличие базы данных и взаимодействует с__MigrationHistory Таблица. Как упомянул @Anders Abel, он используется для изучения отложенных миграций, а также для выбора предыдущей модели, чтобы фактически найти то, что изменилось - это особенно важно, если вы добавите явную миграцию в решение, где включены автоматические миграции.

Ваш ответ на вопрос