Как отключить использование таблицы __MigrationHistory в Entity Framework 4.3 Code First?

Я использую Entity Framework 4.3 Code First с настраиваемым инициализатором базы данных, например:

public class MyContext : DbContext
{
    public MyContext()
    {
        Database.SetInitializer(new MyContextInitializer());
    }
}

public class MyContextInitializer : CreateDatabaseIfNotExists<MyContext>
{
    protected override void Seed(MyContext context)
    {
        // Add defaults to certain tables in the database

        base.Seed(context);
    }
}

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

Когда я снова запускаю свое приложение, я получаю эту ошибку:

Ошибка сервера в приложении '/'

Модель, поддерживающая контекст MyContext, изменилась с момента создания базы данных. Рассмотрите возможность использования Code First Migrations для обновления базы данных (http://go.microsoft.com/fwlink/?LinkId=238269).

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

Сведения об исключении: System.InvalidOperationException: модель, поддерживающая контекст MyContext, изменилась с момента создания базы данных. Рассмотрите возможность использования Code First Migrations для обновления базы данных (http://go.microsoft.com/fwlink/?LinkId=238269).

Используя EFProfiler, я также заметил, что эти запросы выполняются:

-- statement #1
SELECT [GroupBy1].[A1] AS [C1]
FROM   (SELECT COUNT(1) AS [A1]
        FROM   [dbo].[__MigrationHistory] AS [Extent1]) AS [GroupBy1]

-- statement #2
SELECT TOP (1) [Project1].[C1]          AS [C1],
               [Project1].[MigrationId] AS [MigrationId],
               [Project1].[Model]       AS [Model]
FROM   (SELECT [Extent1].[MigrationId] AS [MigrationId],
               [Extent1].[CreatedOn]   AS [CreatedOn],
               [Extent1].[Model]       AS [Model],
               1                       AS [C1]
        FROM   [dbo].[__MigrationHistory] AS [Extent1]) AS [Project1]
ORDER  BY [Project1].[CreatedOn] DESC

Как я могу предотвратить это?


person Kristof Claes    schedule 29.06.2012    source источник


Ответы (2)


Сначала я был уверен, что это потому, что вы устанавливаете инициализатор по умолчанию в ctor, но немного исследуя, я обнаружил, что инициализатор запускается не при создании контекста, а при первом запросе/добавлении чего-либо.

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

 public class Initializer : IDatabaseInitializer<Context>
    {

        public void InitializeDatabase(Context context)
        {
            if (!context.Database.Exists())
            {
                context.Database.Create();
                Seed(context);
                context.SaveChanges();
            }
        }

        private void Seed(Context context)
        {
            throw new NotImplementedException();
        }
    }

Это не должно проверять совместимость, и если база данных отсутствует, она ее создаст.

ОБНОВЛЕНИЕ: «Контекст» должен быть типом вашей реализации DbContext.

person Mikael Eliasson    schedule 29.06.2012
comment
Спасибо, Микаэль. Ваше решение, кажется, работает. Вы уверены, что по умолчанию CreateDatabaseIfNotExists не делает ничего больше, чем if (!context.Database.Exists()) { context.Database.Create(); Seed(context); }? - person Kristof Claes; 29.06.2012
comment
Я не уверен, но в случае, когда БД не существует, они генерируют точно такой же sql, по крайней мере, в соответствии с Sql Profiler. - person Mikael Eliasson; 29.06.2012
comment
Я только что декомпилировал EntityFramework.dll, чтобы посмотреть, что он делает. Взгляните на эту суть: gist.github.com/3017384 Самая важная недостающая часть — это context.SaveChanges(); после звоню Seed(context);. Спасибо, что указали мне правильное направление! - person Kristof Claes; 29.06.2012
comment
А, понятно. Я бы, вероятно, поместил SaveChanges в метод Seed, но это лучше, поскольку он совместим, если они когда-либо изменят поведение по умолчанию, и вы хотите вернуться к наследованию. - person Mikael Eliasson; 29.06.2012
comment
Должен ли «Контекст» в этом решении быть не DbContext? Когда я включил это в свое решение, единственный найденный контекст находится в пространстве имен System.Remoting.Contexts. Если я изменю их на DbContext, все будет выглядеть правильно. - person Jeremy Wiebe; 16.10.2012
comment
Джереми, Context должен быть вашей реализацией DbContext (класс, в котором у вас есть DbSet). - person Mikael Eliasson; 16.10.2012
comment
@MikaelEliasson Ах, это имеет смысл. Спасибо. Мы никогда не будем использовать часть создания базы данных этого инициализатора, поэтому мы просто будем использовать DbContext, и, похоже, он работает над подавлением запросов __MigrationHistory. - person Jeremy Wiebe; 16.10.2012

Передать null в System.Data.Entity.Database

public static void SetInitializer<TContext>(
    IDatabaseInitializer<TContext> strategy
)
where TContext : DbContext

чтобы отключить инициализацию для вашего контекста. Не реализуйте IDatabaseInitializer, чтобы отключить его.

https://msdn.microsoft.com/en-us/library/system.data.entity.database.setinitializer(v=vs.113).aspx

person Brian    schedule 30.01.2017