问题 如何在Entity Framework 4.3 Code First中禁用__MigrationHistory表的使用?


我正在使用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”上下文的模型已更改。请考虑使用“代码优先迁移”来更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269)。

描述: 在执行当前Web请求期间发生了未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

例外细节: System.InvalidOperationException:自创建数据库以来,支持“MyContext”上下文的模型已更改。请考虑使用“代码优先迁移”来更新数据库(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

我怎么能阻止这个?


12222
2018-06-29 09:14


起源



答案:


起初我确信这是因为你在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();
        }
    }

这不应该检查兼容性,如果缺少数据库,它将创建它。

更新:“Context”应该是DbContext实现的类型


10
2018-06-29 09:53



谢谢,Mikael。您的解决方案似乎有效。你是默认的肯定 CreateDatabaseIfNotExists 没什么 if (!context.Database.Exists()) { context.Database.Create(); Seed(context); }? - Kristof Claes
我不确定但是在没有db存在的情况下,它们根据Sql Profiler至少生成完全相同的sql。 - Mikael Eliasson
我刚刚反编译了EntityFramework.dll以查看它的作用。看看这个要点: gist.github.com/3017384 最重要的缺失部分是 context.SaveChanges(); 打电话后 Seed(context);。谢谢你指点我正确的方向! - Kristof Claes
啊,我明白了。我可能已经将SaveChanges放在Seed方法中,但这更好,因为它们是兼容的,如果它们改变默认行为并且你想要改回到继承 - Mikael Eliasson
此解决方案中的“上下文”应该不是DbContext吗?当我将其提取到我的解决方案中时,找到的唯一Context是在System.Remoting.Contexts命名空间中。如果我将这些更改为DbContext,一切看起来都是正确的。 - Jeremy Wiebe


答案:


起初我确信这是因为你在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();
        }
    }

这不应该检查兼容性,如果缺少数据库,它将创建它。

更新:“Context”应该是DbContext实现的类型


10
2018-06-29 09:53



谢谢,Mikael。您的解决方案似乎有效。你是默认的肯定 CreateDatabaseIfNotExists 没什么 if (!context.Database.Exists()) { context.Database.Create(); Seed(context); }? - Kristof Claes
我不确定但是在没有db存在的情况下,它们根据Sql Profiler至少生成完全相同的sql。 - Mikael Eliasson
我刚刚反编译了EntityFramework.dll以查看它的作用。看看这个要点: gist.github.com/3017384 最重要的缺失部分是 context.SaveChanges(); 打电话后 Seed(context);。谢谢你指点我正确的方向! - Kristof Claes
啊,我明白了。我可能已经将SaveChanges放在Seed方法中,但这更好,因为它们是兼容的,如果它们改变默认行为并且你想要改回到继承 - Mikael Eliasson
此解决方案中的“上下文”应该不是DbContext吗?当我将其提取到我的解决方案中时,找到的唯一Context是在System.Remoting.Contexts命名空间中。如果我将这些更改为DbContext,一切看起来都是正确的。 - Jeremy Wiebe


将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


0
2018-01-30 18:08