First code for SQL Server 2005?

My development database is 2008 R2 where Code First generates a local database using DropCreateIfModelChanges.

My deployment method for production is to generate scripts from a local DB including data and run it during production. This creates all tables, including the EdmMetadata table, and populates it with a hash.

Works: Run the script on another 2008 R2 instance, change the connection string for the Entity model to point to this production instance, run the app.

Doesn't work: Run the script in another 2005 instance, change the connection string for the Entity model to point to this production instance, run the application. I am getting a model change error.

I think it doesn't work because the DB compatibility version is part of the hash. thus, during production, it generates a hash and compares it to the hash stored in the EdmMetadata table. The new hash is different in that it is generated compared to the 2005 database.

I guess I would not have this problem if I were creating a local 2005 database and deploying it to a 2005 instance. However, I am not set for 2005 and do not want all developers to have to install it when 2008 supports 2005 compatibility mode.

How do I get EF to generate the DB in 2005 compatibility mode?

+3


source to share


1 answer


If the only problem is checking model compatibility, you can disable database initializers for your context when working in a production environment where you do not appear to need to initialize the database. You can do it in code like this:

Database.SetInitializer<MyContext>(null);

      

But it's probably better to do it in app.config / web.config for your production application like so:

<entityFramework>
  <contexts>
    <context type="MyNamespace.MyContext, MyAssembly" disableDatabaseInitialization="true" />
  </contexts>
</entityFramework>

      

You will need to upgrade to EF 4.3 for this syntax - see http://blogs.msdn.com/b/adonet/archive/2012/01/12/ef-4-3-configuration-file-settings.aspx . There is also a way to do this in EF 4.1: see http://blog.oneunicorn.com/2011/03/31/configuring-database-initializers-in-a-config-file/ .

You can also try to simply upgrade to EF 4.3, which no longer uses the EdmMetadata table - it uses the __MigrationHistory table instead. This checks the compatibility of the model in a different way. It may still indicate the difference if Code First was creating a different database for 2005 than 2008, which happens sometimes.

You can install SQL Server 2005 Express in your dev box. It's free and will fit your production environment better.

Finally, if none of the above works and you need to force Code First to create a 2005 model / database, you can do so, but that means using the below building blocks. First, you need to create the DbModelBuilder yourself and call the Entity for each of the entity types for which you have a DbSet declared in your context:



var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<User>();
modelBuilder.Entity<Blog>();

      

Here you can freely customize the configuration or use data annotations as usual. OnModelCreating will not be called, so don't freely send calls there - move them here.

Once you have your DbModelBuilder configured, you need to build and compile to get a compiled model that can be passed to the DbContext. It is at this point that you can go to "2005" as a vendor manifest token.

var compiledModel = modelBuilder
    .Build(new DbProviderInfo("System.Data.SqlClient", "2005"))
    .Compile();

      

You should now cache this compiled model in your application domain so that you only build and compile it once. (Usually DbContext does this for you when it creates the model, but if you create the model yourself, you also need to do the caching yourself.)

Finally, you need to pass the compiled model to your context's constructor every time you need to use it, and for that constructor to pass the model to the underlying constructor.

public class MyContext : DbContext
{
    public MyContext(DbCompiledModel model)
        : base(model)
    {
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Blog> Blogs { get; set; }
}

      

There are other constructor overloads for passing a name or connection string if you need them.

+2


source







All Articles