Entity Framework 4.1 自数据库创建以来,支持上下文的模型在创建数据库后立即发生了变化

发布于 2024-12-12 18:41:21 字数 608 浏览 0 评论 0原文

我正在开发一个项目,该项目使用 Entity Framework 4.1 将各种对象保存到数据库(代码优先)。

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

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

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

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

我是新来的 - 感谢您的帮助!

I am working on a project which uses Entity Framework 4.1 for persisting our various objects to the database (code first).

I am testing in Visual Studio with a local SQL Express DB, and our Jenkins server deploys committed code to a testing server. When this happens I temporarily change my local connection string to point to the testing DB server and run a unit test to re-create the test database so that it matches our latest entities, etc.

I've recently noticed our testing server is giving this error:

The model backing the 'EntityFrameworkUnitOfWork' 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.

This is usually an indication that our code has changed and I need to run the unit test to re-create the database. Except I just did that! I don't believe there is anything wrong with our deployment process - the DLLs on the test server seem to be the same versions as in my local environment. Are there any other settings or environment factors that can cause this error about the model having changed since the database was created?

I'm new here - thanks for any help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

夏雨凉 2024-12-19 18:41:22

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

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

modelBuilder.Conventions.Remove<IncludeMetadataConvention>();

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

The error you see means that the model hash stored in EdmMetadata table is different from the model hash computed from the model in the application. Because you are running database creation from a different application (your dev. application) it is possible that those two differ. Simple advice here is: don't use different applications for database creation and instead let your main application create the database (either automatically or for example with some admin interface).

As another option you should be able to turn off this check completely by removing the convention responsible for these checks:

modelBuilder.Conventions.Remove<IncludeMetadataConvention>();

Model hash computation is dependent on current entities in your application (any simple change result in different model hash) and on database server versions / manifest. For example a model deployed on SQL server 2005 and 2008 will have different model hash (Express vs. Full or 2008 vs. 2008 R2 should not result in different model hash).

拔了角的鹿 2024-12-19 18:41:22

由于不同平台之间的反射顺序差异,可能会发生这种情况。要进行验证,您可以使用 EdmxWriter API 来比较两个环境中的 EDMX。如果任何表具有不同的列顺序,那么这就是问题所在。

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

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

This can happen due to reflection ordering differences across different platforms. To verify, you can use the EdmxWriter API to compare the EDMX from both environments. If any of the tables have different column ordering, then this is the issue.

To workaround, you can change the way your test database gets updated such that it is updated from your test server rather than your local box.

We are going to fix this issue in the next release.

箹锭⒈辈孓 2024-12-19 18:41:22

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

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

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

In the code-first approach, the SSDL is generated during the execution of the code. One of the informations included in the generated SSDL is the name of the provider used in the DbConnection. As you said, you're connecting to different databases engines, so you must use two different providers. This completly changes the output of the hashing function.

The below code was extracted from the EntityFramework assembly:

using (XmlWriter writer = XmlWriter.Create(output, settings))
{
    new SsdlSerializer().Serialize(database, providerInfo.ProviderInvariantName, providerInfo.ProviderManifestToken, writer);
}
风为裳 2024-12-19 18:41:22

这可能会有所帮助,并且指向 Scott G 博客的链接肯定会解决您的问题,请检查此问题 链接

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

编辑 2:您还可以查看 如果您首先在集成服务器上使用数据库

编辑3:这是一个 更多详细的答案,就像 Scott G 的答案一样

This might help and the link to Scott G blog will sure be a solution to your problem check this question link

Edit 1: this is the link to Scott G blog

Edit 2: You may also check this if you use a database first on integration server

Edit 3: This is a more detailed answer like the one from Scott G

水波映月 2024-12-19 18:41:22

运行应用程序的两台服务器是否运行不同的操作系统(或服务包?)似乎使用的 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;
}

您可以使用以下方法进行测试反射在每个服务器上调用以下 2 个(内部/私有)方法。

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

Are the two servers running your application running different operating systems (or service packs?) It appears the SHA256CryptoService used can throw a PlatformNotSupportedException which causes it to fallback to another method.

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;
}

You may be able to test this by using reflection to invoke the following 2 (internal/private) methods on each server.

MetaDataWorkspace.ToMetadataWorkspace(DbDatabaseMapping, Action<string>)
CodeFirstCachedMetadataWorkspace.ComputeSha256Hash(string xml);
圈圈圆圆圈圈 2024-12-19 18:41:22

实体框架代码首先创建一个名为 EdmMetadata 的表。它保留了当前模型的哈希值。运行应用程序后,EF 将检查正在使用的模型是否与数据库“了解”的模型相同。

如果您想执行数据库迁移,我建议您使用 EF 代码优先迁移,尽管它仍然是 alpha。

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

手动处理架构更改 - 这意味着将 EdmMetadata 表的内容以及所有更改一起移动到测试服务器

,或者

将 db 初始值设定项设置为 DropCreateDatabaseIfModelChanges (或者更好的是从并使用 Seed() 方法写入初始数据)。要设置初始值设定项,请在应用程序启动时调用 Database.SetInitializer() 或使用 appSettings

<add key="DatabaseInitializerForType Fully.Qualified.Name.Of.Your.DbContext," value="Fully.Qualified.Name.Of.The.Initializer" />

Entity Framework code first creates a table called EdmMetadata. It keeps a hash of your current model. Once you run the application EF checks if the model being used is the same as the model that the db 'knows about'.

If you want to perform database migration, I suggest you use EF Code first migrations though it's still an alpha.

If you don't want to use migrations you can either:

handle the schema change manually - that means moving the content of the EdmMetadata table to the test server along with all the changes

or

set the db initializer to DropCreateDatabaseIfModelChanges (or better something derived from it and use the Seed() method to write the initial data). To set the initialzer either call Database.SetInitializer() on application start or use the appSettings

<add key="DatabaseInitializerForType Fully.Qualified.Name.Of.Your.DbContext," value="Fully.Qualified.Name.Of.The.Initializer" />
鹤仙姿 2024-12-19 18:41:22

我只是不小心重命名了 .mdf 文件并收到此错误。所以还要寻找这个。

I only accidentally renamed my .mdf file and got this error. So look also for this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文