Лучший способ пошагового заполнения данных в Entity Framework 4.3
Я использую Entity Framework 4.3 в существующей базе данных, и у меня есть несколько сценариев, которые я пытаюсь удовлетворить.
Во-первых, если я удаляю свою базу данных, я бы хотел, чтобы EF воссоздал ее с нуля - для этого я успешно использовал инициализатор базы данных CreateDatabaseIfNotExists.
Во-вторых, если я обновляю свою модель и база данных уже существует, я бы хотел, чтобы база данных обновлялась автоматически - я успешно использовал Entity Framework 4.3 Migrations для этого.
Итак, вот мой вопрос. Скажем, я добавляю в свою модель новую таблицу, для которой требуются некоторые справочные данные, что является наилучшим способом обеспечения создания этих данных как при выполнении инициализатора базы данных, так и при выполнении миграции. Я хочу, чтобы данные создавались при создании базы данных с нуля, а также при обновлении базы данных в результате выполнения миграции.
В некоторых примерах миграции EF я видел, как люди использовали функцию SQL() в методе UP миграции для создания начальных данных, но, если возможно, я бы предпочел использовать контекст для создания начальных данных (как вы видите в большинстве примеров инициализатора базы данных). мне кажется странным, что вы будете использовать чистый sql, когда вся идея EF абстрагируется от этого. Я пытался использовать контекст в методе UP, но по какой-то причине он не думал, что таблица, созданная в процессе миграции, существовала, когда я пытался добавить начальные данные непосредственно под вызовом для создания таблицы.
Любая мудрость высоко ценится.
2 ответа
Если вы хотите использовать сущности для заполнения данных, вы должны использовать Seed
метод в вашей конфигурации миграции. Если вы генерируете свежий проект Enable-Migrations
вы получите этот класс конфигурации:
internal sealed class Configuration : DbMigrationsConfiguration<YourContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(CFMigrationsWithNoMagic.BlogContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
Способ, которым исходные данные миграции не очень эффективны, потому что предполагается, что они используются для некоторого очень простого заполнения. Каждое обновление до новой версии будет проходить через весь набор и пытаться обновить существующие данные или вставить новые данные. Если вы не используете AddOrUpdate
метод расширения, вы должны вручную убедиться, что данные будут добавлены в базу данных, только если они еще не представлены.
Если вам нужен эффективный способ посева, потому что вы должны заполнить много данных, вы получите лучший результат с помощью:
public partial class SomeMigration : DbMigration
{
public override void Up()
{
...
Sql("UPDATE ...");
Sql("INSERT ...");
}
public override void Down()
{
...
}
}
Я бы не рекомендовал использовать Sql()
звонки в вашем Up()
метод, потому что (IMO) это действительно предназначено для фактического кода миграции, для которого нет встроенной функции, а не начального кода.
Мне нравится думать о начальных данных как о чем-то, что может измениться в будущем (даже если моя схема этого не сделает), поэтому я просто пишу "защитные" проверки вокруг всех моих вставок в начальную функцию, чтобы убедиться, что операция не сработала ранее.
Рассмотрим сценарий, в котором у вас есть таблица "Типы", которая начинается с 3 записей, но затем вы добавляете 4-ю. Вам не нужно "миграция", чтобы решить эту проблему.
С помощью Seed()
также дает вам полный контекст для работы, что намного лучше, чем использование простых строк SQL в Sql()
метод, который продемонстрировал Ладислав.
Кроме того, имейте в виду, что преимущество использования встроенных методов EF как для кода миграции, так и для исходного кода состоит в том, что ваши операции с базами данных остаются независимыми от платформы. Это означает, что ваши изменения схемы и запросы могут выполняться на Oracle, Postgre и т. Д. Если вы пишете реальный необработанный SQL, то вы потенциально необязательны.
Вы можете быть менее обеспокоены этим, поскольку 90% людей, использующих EF, будут использовать только SQL Server, но я просто добавлю его, чтобы дать вам другой взгляд на решение.