【问题标题】:How can I disable the use of the __MigrationHistory table in Entity Framework 4.3 Code First?如何在 Entity Framework 4.3 Code First 中禁用 __MigrationHistory 表?
【发布时间】:2012-06-29 09:14:02
【问题描述】:

我正在使用带有自定义数据库初始化程序的 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 迁移来更新数据库 (http://go.microsoft.com/fwlink/?LinkId=238269)。

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

异常详细信息: System.InvalidOperationException:支持“MyContext”上下文的模型自数据库创建以来已更改。考虑使用 Code First 迁移来更新数据库 (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

我怎样才能防止这种情况发生?

【问题讨论】:

    标签: ef-code-first entity-framework-4.3 entity-framework-migrations


    【解决方案1】:

    起初我确定这是因为您在 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 实现的类型

    【讨论】:

    • 谢谢,米凯尔。您的解决方案似乎有效。你确定默认的CreateDatabaseIfNotExists 只做if (!context.Database.Exists()) { context.Database.Create(); Seed(context); } 吗?
    • 我不确定,但在不存在 db 的情况下,它们至少根据 Sql Profiler 生成完全相同的 sql。
    • 我刚刚反编译了 EntityFramework.dll 来看看它做了什么。看看这个要点:gist.github.com/3017384 最重要的缺失部分是在调用Seed(context); 之后的context.SaveChanges();。感谢您为我指明正确的方向!
    • 啊,我明白了。我可能会将 SaveChanges 放在 Seed 方法中,但这会更好,因为如果它们更改默认行为并且您想改回继承,则它是兼容的
    • 此解决方案中的“上下文”不应该是 DbContext 吗?当我将其拉入我的解决方案时,找到的唯一上下文位于 System.Remoting.Contexts 命名空间中。如果我将这些更改为 DbContext,一切看起来都是正确的。
    【解决方案2】:

    将 null 传递给 System.Data.Entity.Database's

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 2013-10-28
      • 1970-01-01
      • 2016-07-29
      • 1970-01-01
      相关资源
      最近更新 更多