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

Лучший способ пошагового семени данных в Entity Framework 4.3

Я использую Entity Framework 4.3 в существующей базе данных, и у меня есть несколько сценариев, которые я пытаюсь удовлетворить.

Во-первых, если я удалю свою базу данных, я бы хотел, чтобы EF воссоздал, если с нуля - я успешно использовал для этого инициализатор базы данных CreateDatabaseIfNotExists.

Во-вторых, если я обновляю свою модель, и база данных уже существует, я бы хотел, чтобы база данных обновлялась автоматически - я успешно использовал Entity Framework 4.3. Миграции для этого.

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

В некоторых примерах миграции EF я видел, как люди используют функцию SQL() в методе UP для переноса данных для создания исходных данных, но, если возможно, я предпочел бы использовать контекст для создания исходных данных (как вы видите в большинстве баз данных примеры инициализации), поскольку мне кажется странным, что вы использовали бы чистый sql, когда вся идея EF абстрагирует это. Я попытался использовать контекст в методе UP, но по какой-то причине он не думал, что таблица, созданная при миграции, существовала, когда я пытался добавить данные семян непосредственно под вызовом для создания таблицы.

Любая мудрость очень ценится.

4b9b3361

Ответ 1

Если вы хотите использовать сущности для высева данных, вы должны использовать метод 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()
    {
        ...
    }
}

Ответ 2

Я бы не рекомендовал использовать вызовы Sql() в вашем методе Up(), потому что (IMO) это действительно предназначено для реального кода миграции, для которого нет встроенной функции, а не кода семени.

Мне нравится думать о данных семян как о чем-то, что может измениться в будущем (даже если моя схема не работает), поэтому я просто пишу "защитные" проверки всех моих вставок в функции семени, чтобы убедиться, что операция ранее не срабатывал.

Рассмотрим сценарий, в котором у вас есть таблица "Типы", которая начинается с 3 записей, но затем вы добавите четвертый. Для этого вам не требуется "миграция".

Использование Seed() также дает вам полный контекст для работы, что намного лучше, чем использование простых строк sql в методе Sql(), который продемонстрировал Ладислав.

Кроме того, имейте в виду, что преимущество использования встроенных методов EF для кода перехода и кода семени заключается в том, что ваши операции с базой данных остаются нейтральными по отношению к платформе. Это означает, что ваши изменения схемы и запросы могут выполняться на Oracle, Postgre и т.д. Если вы напишете фактический необработанный SQL, тогда вы потенциально заблокируете себя без необходимости.

Вы можете быть менее обеспокоены этим, поскольку 90% людей, использующих EF, будут когда-либо сталкиваться с SQL Server, но я просто бросаю его туда, чтобы дать вам другую перспективу в решении.