2

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.

devuxer
  • 41,681
  • 47
  • 180
  • 292
  • 1
    possible duplicate of [Entity Framework Code Only error: the model backing the context has changed since the database was created](http://stackoverflow.com/questions/3552000/entity-framework-code-only-error-the-model-backing-the-context-has-changed-since) – Kyle Trauberman May 27 '11 at 23:38
  • @Kyle, My existing database *was* created by Code First and *does* have an EdmMetadata table with a hash. So, I don't believe this is a duplicate. – devuxer May 28 '11 at 00:00
  • 1
    It sounds like you created your db from your model and then updated the model post db creation. Since the definition of the db was dependent on the original model you need to update the db on production to reflect your current data model. Just a guess. – BentOnCoding May 28 '11 at 00:05
  • 1
    @DanM Have you compared the hash values on the local and production servers? – Steve Mallory May 28 '11 at 00:51
  • @Robotsushi, my model hasn't changed in weeks, and I regenerated my database today just in case. After regenerating, I ftp'd the new database to the production server. I don't see how the database can possibly be out of date. I'm using the same database for testing, and I get no error locally. – devuxer May 28 '11 at 05:59
  • @Steve Mallory, the hash values are exactly the same because the test and production databases are the same. – devuxer May 28 '11 at 06:11

3 Answers3

6

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>();
}
Mark
  • 21,067
  • 14
  • 53
  • 71
  • @Mark, There is *no* difference between my test db and my production db. Exact same .sdf file. I'm just copying the file to the production server. Here's my basic workflow: 1. Edit a POCO entity. 2. Test/Debug my app (locally). 3. Receive "The model backing 'foobar' context has changed...". 4. Think "Oh yeah, I have to regenerate the database!" 5. Run custom db generator that recreates db and seeds w/ data. 6. Test/debug app again (locally) --> works fine. 6. Publish app to production server (ftp). 7. Open a page in browser. 8. Receive "The model backing 'foobar' context has changed...". Why? – devuxer May 28 '11 at 17:06
  • Can you give TryGetModelhash a try? Compare the value it returns against the ModelHash in the production and local EdmMetadata table. The values must be different or you wouldn't receive that error. Why they're different we'll have to figure out. I'd first start with that though. Verify the hashes actually are different and you're not running into a bug of some type. – Mark May 28 '11 at 20:13
  • http://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.edmmetadata.trygetmodelhash(v=vs.103).aspx – Mark May 28 '11 at 20:14
  • I was just thinking some more about this. I'm actually working on an Entity issue today so Entity has been on my mind. Anyway. I realize this is obvious but double check you have the same EntityFramework DLL on both machines. There were changes between the RC and the RTW. – Mark May 28 '11 at 21:46
  • Mark, that was it! I thought I had the RTW version installed, but I guess I didn't, or at least it let me install again. Then, I redid all my references to EntityFramework in all my projects, rebuilt my database, and republished. Now the hashes are consistent, and it's working as designed. Thanks for all your help. – devuxer May 29 '11 at 21:26
3

Disable validation:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
}
Diego Mijelshon
  • 52,548
  • 16
  • 116
  • 154
1

Check out this video:

http://www.pluralsight-training.net/microsoft/players/PSODPlayer.aspx?author=scott-allen&name=mvc3-building-data-i&mode=live&clip=0&course=aspdotnet-mvc3-intro

This is part of the free plural sight training available on http://asp.net/mvc. Click the "When Classes Change" video on the left side of the page, then go to 8:30 in the video.

Apparently if you delete the EDMMetadata table in the DB, EF will disable model validation.

Kyle Trauberman
  • 25,414
  • 13
  • 85
  • 121
  • Thanks Kyle, but why do I want to disable model validation? – devuxer May 28 '11 at 05:42
  • Kyle, see my edit. Deleting EdmMetadata *does* work, but I don't understand why I should need to do this. Why is the exact same database file considered up-to-date when I run locally but when I upload it to the production server, suddenly it's out-of-date. Thanks. – devuxer May 28 '11 at 06:10