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

Entity Framework 5 Миграции: настройка начальной миграции и одиночное семя базы данных

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

Вот что я сделал в своей функции запуска приложения.

protected void Application_Start()
{
    Database.SetInitializer(
        new MigrateDatabaseToLatestVersion< MyContext, Configuration >() );
    ...
}

Я запустил команду Enable-Migrations в моем проекте репозиториев, и я подумал, что это создаст исходный файл миграции, но единственный файл, который он создал, был Configuration

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

Однако он запускает функцию seed в моем файле Configuration при каждом запуске веб-сайта и повторяет все семенные данные снова и снова.

Я представил себе, что он создаст файл initial migration, так как блог, который я прочитал, предположил, что он будет, и я мог бы разместить семенные данные там, но он не

Может кто-нибудь объяснить, как я должен настраивать БД в коде, чтобы он только семя один раз?


LINK: сообщение блога о миграции, которое я выполнил


Хотя это довольно интересно для использования EF migrate.exe, я с тех пор перешел на использование roundhouse для запуска миграции. Я по-прежнему использую EF для выравнивания моих миграций на основе моделей, но я написал небольшое консольное приложение, чтобы записать миграции в файлы SQL. Затем я использую roundhouse для выполнения самих миграций через мои скрипты сборки rake. Там немного больше процесса, но он гораздо более стабилен, чем использование EF для выполнения миграции "на лету" при запуске приложения.

4b9b3361

Ответ 1

Это оказалось популярным, поэтому я обновил его в свете отзывов от других. Главное знать, что метод Seed в классе Configuration запускается КАЖДОЕ время запуска приложения, что не соответствует комментарию в методе шаблона. См. Ответ от кого-то из Microsoft на этот пост о том, почему это - благодаря Джейсону Лирмуту за то, что он нашел это.

Если вы, как и я, только хотите запустить обновления базы данных, если есть какие-либо ожидающие миграции, вам нужно немного поработать. Вы можете найти это, если есть ожидающие миграции, вызвав migrator.GetPendingMigrations(), но вы должны сделать это в ctor, так как список ожидающих миграции очищается до вызова метода Seed. Код для реализации этого, который входит в класс Migrations.Configuration, выглядит следующим образом:

internal sealed class Configuration : DbMigrationsConfiguration<YourDbContext>
{ 
    private readonly bool _pendingMigrations;

    public Configuration()
    {
        // If you want automatic migrations the uncomment the line below.
        //AutomaticMigrationsEnabled = true;
        var migrator = new DbMigrator(this);
        _pendingMigrations = migrator.GetPendingMigrations().Any();
    }

    protected override void Seed(MyDbContext context)
    {
        //Microsoft comment says "This method will be called after migrating to the latest version."
        //However my testing shows that it is called every time the software starts

        //Exit if there aren't any pending migrations
        if (!_pendingMigrations) return;

        //else run your code to seed the database, e.g.
        context.Foos.AddOrUpdate( new Foo { bar = true});
    }
}

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

Ответ 2

Вы можете добавить миграцию вручную и заполнить ее любым желаемым кодом высева? В консоли консоли диспетчера пакетов:

Add-Migration [Name]

Затем вы можете отредактировать файл, созданный для вас в папке переноса.

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

internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
    public Configuration()
    {
        // If you want automatic migrations as well uncomment below.
        // You can use both manual and automatic at the same time, but I don't recommend it.
        //AutomaticMigrationsEnabled = true;
        //AutomaticMigrationDataLossAllowed = true;
    }

    protected override void Seed(MyContext 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.

        context.FontFamilies.AddOrUpdate(
            f => f.Id,
            new FontFamily { Id = 1, PcName = "Arial" },
            new FontFamily { Id = 2, PcName = "Times New Roman" },
        });

Я использую это в Global.asax:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        // Any migrations that haven't been applied before will
        // automatically be applied on Application Pool restart

        Database.SetInitializer<MyContext>(
            new MigrateDatabaseToLatestVersion<MyContext,
            MyApp.Migrations.Configuration>()
        );
    }
}

Ответ 3

Это то, о чем я и думал в прошлом. У меня есть определенные таблицы в моей базе данных, которые заполняются в моем событии Seed, и теперь я просто проверяю, не является ли один из них пустым в методе Seed. Если есть строки, метод Seed не запускается. Не непогрешимо, но делает трюк.

Ответ 4

Ответ на этот вопрос SO объясняет, почему Seed запускается каждый раз, когда приложение запускается.

Я использую метод Jon Smiths, но я поставил чек на ожидающий запрос миграции в блоке #if следующим образом:

#if (!DEBUG)
            if (!_pendingMigrations) return;
#endif

Таким образом, когда я отлаживаю метод Seed, всегда выполняется, чтобы повторно заполнить мои данные семени - полезно, когда я удаляю во время тестирования, и т.д., но я не получаю перфоманс при выпуске.