EF代码首先认为数据库已过期 - 仅在生产中 [英] EF Code First thinks database is out of date -- only in production

查看:117
本文介绍了EF代码首先认为数据库已过期 - 仅在生产中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用SQL Server CE 4.0和实体框架4.1代码的ASP.NET MVC 3应用程序。 在本地工作正常,但在生产中,它会失败,并显示以下错误:


自创建数据库以来,foobar的上下文已经改变。手动删除/更新数据库,或者使用IDatabaseInitializer实例调用Database.SetInitializer。例如,DropCreateDatabaseIfModelChanges策略将自动删除并重新创建数据库,并且可以选择为新数据添加种子。


我已经验证我的应用程序dll和数据库文件在远程服务器上是最新的,但我继续收到此错误。



任何想法可能是什么问题? p>

注意:我使用的是RTF版本的Entity Framework 4.1,而不是CTP。



编辑



如果我删除了EdmMetadata表,并将数据库重新发布到生产服务器,我不再收到错误。但是,我完全不明白为什么我应该这样做。模型尚未更改。几周没有改变,我今天重建数据库。我猜这个整体的关键是哈希。与...进行比较的EdmMetadata哈希是什么?



编辑2



根据Mark S的答案,将EdmMetadata表中的哈希与SSDL的散列进行比较。但是,解决方案中的任何地方都没有实际的SSDL文件(没有扩展名为.ssdl的文件,没有包含ssdl的文件)。那么,SSDL实际存储在哪里?是否在设计时或运行时生成?



编辑3



回答我自己的问题,SSDL 在运行时生成和缓存(更多细节这里),但是看看SSDL的实际模式,我不知道我看到任何可能会改变的东西,因为项目的DLL住在不同的位置一个不同的服务器。






注意:我正在使用完全相同的数据库文件(.sdf)进行测试和制作。我将文件从bin / App_Data ftp到生产服务器上的App_Data文件夹。我也是ftp的项目DLL。所以测试和生产之间唯一不同的是这些文件存在于不同的地方。



另外,只是为了记录,这里是我的连接字符串:



DataSource = | DataDirectory | foobar.sdfproviderName =System.Data.SqlServerCe.4.0 p>

编辑4(最终编辑?)



问题原来是一个DLL问题。我认为一个不同版本的EntityFramework DLL被远程与本地使用。解决方案是确保我有最新版本的EF 4.1(RTW),清除和重新添加引用,重新生成数据库并重新发布。

解决方案

回应与被比较的EdmMetadata哈希是什么?



EdmMetadata表格允许Code First确定代码中的模型是否与数据库中的模型相同。该表包含一个单行,它是SSDL的散列。 SSDL代表商店模式定义语言,是用于描述实体模型和模型之间的映射的基于XML的语言。



您可以阅读有关SSDL的更多信息并查看规范请访问 http://msdn.microsoft.com/en-us/library/bb399559。 aspx



你提到这些事情在本地工作,但不在生产中。您是否允许代码优先构建本地和生产数据库?生产数据库是否已经存在或以其他方式生成?



CodeFirst正在报告数据库中的哈希与当前模型的哈希不匹配,所以某些东西必须是不同的。确定可能是一个挑战。



将EdmMetadata表映射到EdmMetadata类。该类中有一个TrygetModelHash方法,您可以使用它来获取给定上下文的哈希值。如果你很沮丧,可以使用它将当前的模型与生产数据库中的哈希进行比较。这至少让你无需经常建立一个新的数据库来进行测试。



如果需要,您还可以指示Code First排除EdmMetadata表。 >

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove& IncludeMetadataConvention>();
}


I have an ASP.NET MVC 3 app that is using SQL Server CE 4.0 and Entity Framework 4.1 Code First. It works fine locally, but in production, it fails with the following error:

The model backing the 'foobar' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data.

I've verified that my application dll and database file are up-to-date on the remote server, but I continue to get this error.

Any idea what the problem could be?

Note: I'm using the RTF version of the Entity Framework 4.1, not CTP.

Edit

Okay, if I delete the EdmMetadata table, and re-publish the database to the production server, I no longer get the error. However, I completely don't understand why I should have to do this. The model has not changed. It hasn't changed in weeks, and I rebuilt the database just today. I guess the key to this whole thing is the hash. What is the EdmMetadata hash being compared against?

Edit 2

According to Mark S's answer, the hash in the EdmMetadata table is compared against a hash of the SSDL. However, there is no actual SSDL file (no file with extension .ssdl and no file containing "ssdl") anywhere in the solution. So, where is the SSDL actually stored? Is it generated at design time or run time?

Edit 3

To answer my own question, SSDL does get generated and cached at runtime (more details here), but looking at the actual schema of SSDL, I'm not sure I see anything that could possibly change simply because the project's DLL lives in a different location on a different server.


Note: I'm using the exact same database file (.sdf) for test and production. I'm literally ftp-ing the file from bin/App_Data to the App_Data folder on the production server. I'm also ftp-ing the project DLL. So, the only thing that should be different between test and production is that these files live in a different place.

Also, just for the record, here is my connection string:

DataSource=|DataDirectory|foobar.sdf" providerName="System.Data.SqlServerCe.4.0

Edit 4 (final edit?)

The problem turned out to be a DLL issue. I think a different version of the EntityFramework DLL was being used remotely vs. locally. The solution was to make sure I had the latest version of EF 4.1 (RTW), clear and re-add references, regenerate the database, and re-publish. Everything is now working great.

解决方案

In response to "What is the EdmMetadata hash being compared against?"

The EdmMetadata table allows Code First to determine if the model in your code is the same as the model in your database. The table contains a single row which is a hash of your SSDL. SSDL stands for Store Schema Definition Language and is an XML based language used to describe an Entity model and the mappings between models.

You can read more about SSDL and view the specification at http://msdn.microsoft.com/en-us/library/bb399559.aspx

You mention that things work fine locally but not in production. Are you allowing Code First to build both the local and production databases? Is the production database already existing or being generated in another fashion?

CodeFirst is reporting that the hash in the database doesn't match the present model's hash so something must be different. Figuring out what may be a challenge.

The EdmMetadata table is mapped to the EdmMetadata class. There is a TrygetModelHash method in this class which you can use to get the hash for a given context. If you're desparate you could use this to compare your current model to the hash that's in your production database. This would at least keep you from having to build a new database constantly just for testing.

You can also instruct Code First to exclude the EdmMetadata table if desired.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
}

这篇关于EF代码首先认为数据库已过期 - 仅在生产中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆