Entity Framework Code Only 错误: 上下文的模型与创建数据库时不同

51
我创建了一个“仅代码”POCO,用于针对使用Entity Framework 4和CTP4的现有数据库。当我运行查询时,我收到如下错误:

 

“xyzContext”上下文的模型支持已经自创建数据库以来发生了更改。要么手动删除/更新数据库,要么使用IDatabaseInitializer实例调用Database.SetInitializer。例如,RecreateDatabaseIfModelChanges策略将自动删除并重新创建数据库,并可选择用新数据填充它。

我不清楚为什么会发生这种情况或者我可以做些什么更改。我仅仅创建了POCO,定义了一个简单的DbContext,进行了一些调整,然后尝试运行简单的查询。由于我正在使用“仅代码”,因此我不知道是否需要进行任何配置设置。而且我肯定不想重新创建或删除数据库,因为它是现有的数据库。

谢谢任何想法。

7个回答

80

我在Scott Guthrie的博客文章的评论中找到了答案。

http://weblogs.asp.net/scottgu/archive/2010/08/03/using-ef-code-first-with-an-existing-database.aspx

如果你看到这个异常错误:

"The model backing the 'Production' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance."

以下是问题的原因和解决方案:

当一个模型被创建时,我们会运行DatabaseInitializer,用于执行像创建数据库(如果不存在)或添加种子数据等操作。默认的DatabaseInitializer会尝试将需要使用该模型的数据库架构与存储在EdmMetadata表中的架构哈希值进行比较。但是在现有数据库中没有EdmMetadata表,因此也就没有哈希值。在当前实现下,如果缺少该表,则会抛出异常错误。在最终版本发布之前,我们将致力于更改这种行为。在此期间,现有的数据库通常不需要任何数据库初始化程序,因此可以通过调用以下方法来关闭你的上下文类型的数据库初始化程序:

Database.SetInitializer<Production>(null);

4
2013年我也遇到过与您完全相同的问题,当时按照您的答案解决了。他们为什么没有修复它呢?是否有EF5的新模式? - rism
2
FYI,我在EF6中也遇到了同样的问题,这个答案解决了我的问题(将集成的asp.net身份生成表放在我现有的SQL Server数据库之上)。 - Rachael
3
我使用EF6手动更新了数据库并删除了迁移表。 - Simon MᶜKenzie
3
我解决问题时删除的表格是我之前构建示例中的__MigrationHistory。这样做解决了问题。 - CoderRoller
1
@CoderRoller,没错!删除 __MigrationHistory 表已经解决了这个问题。 - Anton Lyhin
显示剩余2条评论

32

这是使用EF和预先存在的数据库时,在CTP4中存在的一个错误。

您可以通过调用以下方法来修复它:

Database.SetInitializer<YourContext>(null);

在 Global.asax 的 Application_Start 方法中


我正在使用MVC3。我已经向模型类添加了一个额外的列。我还在global.asax中输入了你的代码。然而,我仍然遇到错误。我认为旧的数据库没有被删除或重新创建。我该如何向模型添加新列并且删除并重新创建数据库? - bonCodigo
protected void Application_Start() { Database.SetInitializer<MVCMovie1.Models.MovieDBContext>(null); AreaRegistration.RegisterAllAreas(); `RegisterGlobalFilters(GlobalFilters.Filters);` `RegisterRoutes(RouteTable.Routes);` `}` - bonCodigo
因为这个问题不是一个ASP.NET问题,所以被踩了。 - Jared Beach

13

我之前在评论中留言,当时我只是随意尝试EF5以熟悉其工作原理。现在我正在编写“实际”的代码,并且已经远离在代码中为每个上下文设置数据库初始化器,因为我已经决定使用MEF来实例化任何DbContext并将所有配置依赖项注入为组合部件。

所以,我立即遇到了上述错误,但这次我选择使用以下配置文件条目解决它。

<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <contexts>
      <context type="Basd.Erp.ContactContext, Basd.Erp" disableDatabaseInitialization="true"></context>
    </contexts>
  </entityFramework>

在entityFramework的配置文件部分设置disableDatabaseInitialization="true",就可以克服上述错误,由于它不是代码,因此其中一个好处是能够更容易地使用抽象建造者/工厂来创建上下文。


当我的上下文位于单独的程序集中时,我在EF6中仍然遇到了这个问题。正如@rism建议的那样,这是针对抽象的“n层”解决方案的一个好答案。 - trevorc

4
我只需要删除 __MigrationHistory 表就可以了。
背景:
我在更改表名时遇到了此错误。当我向我的某个模型添加注释 [Table("NewTableName")] 后,Entity Framework 生成了一个 __MigrationHistory 表。

1
我遇到了相同的问题 - 重新添加迁移并更新数据库没有起作用,上面的任何答案都不正确。然后我受到启发 - 我正在使用多层(一个Web层,一个数据层和一个业务层)。Web层从未抛出此异常 - 它是业务层(我将其设置为测试和调试的控制台应用程序)抛出的。结果发现业务层没有使用正确的连接字符串来获取数据库并创建上下文。因此,我将连接字符串添加到应用程序配置中,然后它就可以工作了。为其他可能遇到相同问题的人提供这里的信息。

1
谢谢!我不得不浏览很多帖子,直到找到适合我的解决方案;可惜它是一个令人尴尬的简单问题。 - MichaelM

1
我通过将以下内容添加到我的上下文构造函数中解决了这个问题。
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>());

执行此操作后,当数据库已经存在时,我的代码优先迁移会自动运行。

0
在我的情况下,针对这个错误,我只是从“DBControlContext”中删除了“_MigrationHistory”表上的所有记录。希望这对你有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接