Подтвердить что ты не робот

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

Я пытаюсь использовать и понимать 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

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

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

UPDATE: мы отказались от EF Migrations и вместо этого использовали Fluent Migrator и счастливы. Это намного, гораздо быстрее, даже учитывая тот факт, что мы должны написать несколько вещей дважды (один раз для объекта EF и один раз для миграции), и в нем нет проблем, обсуждаемых в этом вопросе.

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

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

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

Изменить

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

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

Ответ 3

OP писал (а):

Но не добавляет-Миграция имеет все, что нужно от DbContext и Конфигурация?

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

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

add-migration

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

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

add-migration -conf Log

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

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

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" во время компиляции; если это так, он использует "LogDeploy". Если нет, он использует значение по умолчанию - строку подключения с тем же именем, что и класс, "LogDb". Это позволяет мне легко развертывать изменения БД на сервере с моего локального компьютера, переключая мою конфигурацию проекта, открывая порт на машине SQL db и запуская:

> update-database -conf Log

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

Ответ 4

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

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

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

Шаги, описанные в видео, следующие:

  • Построить текущую модель из кода
  • Получить предыдущую модель из последней миграции (хранится как моментальный снимок в файле resx)
  • Рассчитайте необходимые изменения базы данных (сделанные EdmModelDiffer)
  • Сгенерирован новый файл миграции

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


Посмотрите также на второе видео, которое называется Миграции - Окружение команды