entity framework4.1自创建数据库以来,创建数据库后立即更改了支持上下文的模型

我正在开发一个项目,它使用Entity Framework 4.1将我们的各种对象持久化到数据库(代码优先)。

我在Visual Studio中使用本地SQL Express DB进行测试,我们的Jenkins服务器将已提交的代码部署到测试服务器。 发生这种情况时,我暂时将本地连接字符串更改为指向测试数据库服务器并运行unit testing以重新创建测试数据库,以使其与我们的最新实体等相匹配。

我最近注意到我们的测试服务器发出了这个错误:

自创建数据库以来,支持’EntityFrameworkUnitOfWork’上下文的模型已更改。 手动删除/更新数据库,或使用IDatabaseInitializer实例调用Database.SetInitializer。 例如,DropCreateDatabaseIfModelChanges策略将自动删除并重新创建数据库,并可选择使用新数据对其进行种子设定。

这通常表明我们的代码已经更改,我需要运行unit testing来重新创建数据库。 除了我刚刚那样做! 我不相信我们的部署过程有任何问题 – 测试服务器上的DLL似乎与我的本地环境中的版本相同。 是否有任何其他设置或环境因素可能导致自创建数据库以来模型发生更改的错误?

我是新来的 – 谢谢你的帮助!

您看到的错误意味着存储在EdmMetadata表中的模型哈希与从应用程序中的模型计算的模型哈希不同。 因为您正在从不同的应用程序(您的开发应用程序)运行数据库创建,所以这两者可能不同。 这里的简单建议是:不要使用不同的应用程序来创建数据库,而是让主应用程序创建数据库(自动或例如使用某个管理界面)。

作为另一种选择,您应该能够通过删除负责这些检查的约定来完全关闭此检查:

 modelBuilder.Conventions.Remove(); 

模型哈希计算依赖于应用程序中的当前实体(任何简单的更改结果在不同的模型哈希中)和数据库服务器版本/清单。 例如,部署在SQL Server 2005和2008上的模型将具有不同的模型散列(Express vs. Full或2008与2008 R2不应导致不同的模型散列)。

这可能是由于不同平台上的reflection排序差异而发生的。 要进行validation,您可以使用EdmxWriter API来比较两种环境中的EDMX。 如果任何表具有不同的列排序,那么这就是问题所在。

要解决此问题,您可以更改测试数据库的更新方式,以便从测试服务器而不是本地方框更新测试数据库。

我们将在下一个版本中修复此问题。

在代码优先方法中,SSDL是在代码执行期间生成的。 生成的SSDL中包含的信息之一是DbConnection中使用的提供程序的名称。 正如您所说,您正在连接到不同的数据库引擎,因此您必须使用两个不同的提供程序。 这完全改变了散列函数的输出。

以下代码是从EntityFramework程序集中提取的:

 using (XmlWriter writer = XmlWriter.Create(output, settings)) { new SsdlSerializer().Serialize(database, providerInfo.ProviderInvariantName, providerInfo.ProviderManifestToken, writer); } 

这可能有所帮助,与Scott G博客的链接肯定会成为您问题的解决方案,请查看此问题链接

编辑1:这是Scott G博客的链接

编辑2:如果您首先在集成服务器上使用数据库,也可以检查此项

编辑3:这是一个更详细的答案,如Scott G的答案

运行应用程序的两台服务器是否运行不同的操作系统(或Service Pack?)看来使用的SHA256CryptoService会抛出一个PlatformNotSupportedException,导致它回退到另一个方法。

http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha256cryptoserviceprovider.sha256cryptoserviceprovider.aspx

 // System.Data.Entity.Internal.CodeFirstCachedMetadataWorkspace private static SHA256 GetSha256HashAlgorithm() { SHA256 result; try { result = new SHA256CryptoServiceProvider(); } catch (PlatformNotSupportedException) { result = new SHA256Managed(); } return result; } 

您可以通过使用reflection来调试每个服务器上的以下2(内部/私有)方法。

 MetaDataWorkspace.ToMetadataWorkspace(DbDatabaseMapping, Action) CodeFirstCachedMetadataWorkspace.ComputeSha256Hash(string xml); 

entity framework代码首先创建一个名为EdmMetadata的表。 它保留了您当前模型的哈希值。 运行应用程序后,EF会检查所使用的模型是否与数据库“知道”的模型相同。

如果您想执行数据库迁移,我建议您使用EF Code首次迁移,尽管它仍然是alpha。

如果您不想使用迁移,您可以:

手动处理模式更改 – 这意味着将EdmMetadata表的内容与所有更改一起移动到测试服务器

要么

将dbd初始化器设置为DropCreateDatabaseIfModelChanges(或者更好的是从它派生的东西,并使用Seed()方法写入初始数据)。 要设置初始化程序,请在应用程序启动时调用Database.SetInitializer()或使用appSettings

  

我只是不小心重命名了我的.mdf文件并得到了这个错误。 所以也请看这个。