可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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!
回答1:
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).
回答2:
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.
回答3:
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);
}
回答4:
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
回答5:
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);
回答6:
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" />
回答7:
I only accidentally renamed my .mdf file and got this error. So look also for this.