Почему для этапа 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 и один раз для миграции), и в нем нет проблем, обсуждаемых в этом вопросе.
Ответы
Ответ 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
)
- Сгенерирован новый файл миграции
Теоретически можно предположить, что было бы достаточно сравнить эту текущую модель с моделью последней миграции для генерации новой миграции.
Но в то же время другие люди тоже могли бы внести изменения в базу данных. Вероятно, поэтому существует и проверка базы данных.
Без этого результирующий файл миграции не должен быть правильным.
Посмотрите также на второе видео, которое называется Миграции - Окружение команды