luksan
luksan

Reputation: 7757

Explicitly invoking DatabaseInitializer

I have a DbContext in an assembly that is shared between two service projects. I have both projects set to start for debugging in Visual Studio. This creates a race condition where the DatabaseInitializer in each service tries to update the database on startup.

To prevent this, I modified my DbContext as follows so as to prevent the DatabaseIntializer from being automatically registered.

public EntityContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<EntityContext>(null);
    }
}

I wanted to disable the DatabaseInitializer inside the DbContext itself so that I would not have to duplicate that SetInitializer() call in every project that happened to reference my DbContext, and based on what I'd read, overriding OnModelCreating() seemed to be the way to do it.

That prevents the DatabaseInitializer from running automatically, but I wanted to create a separate project that I could run manually in order to update the database. So I did something like the following:

static void Main(string[] args)
{
    Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>());
    new EntityContext().Database.Initialize(true);
}

The problem is that this doesn't seem to work - the null initializer set in the OnModelCreating() method apparently overrides anything that I specify in any other call to SetInitializer(). Even if I move the SetIntializer(null) call to a static constructor of the EntityContext class so as to guarantee it is called first it still doesn't work. The only way it works is if I manually call the initializer as follows:

static void Main(string[] args)
{
    new CreateDatabaseIfNotExists<EntityContext>()
        .InitializeDatabase(new EntityContext());
}

But calling the DatabaseInitializer.InitializeDatabase() directly does not seem right, as the Entity Framework infrastructure is supposed to call that.

Is this a bug in EF Code First? What is the "correct" way to go about this?

UPDATE: I decided that manually creating a database script with the Update-Database Package Manager Console command is a better solution than this kludgey project that tries to update the database programmatically.

Upvotes: 1

Views: 2679

Answers (1)

Arthur Vickers
Arthur Vickers

Reputation: 7523

This should work so long as the call to set the initializer is made after the call to disable the initializer. Neither OnModelCreating or the static EntityContext initializer do that in your case. The static initializer will only be called when you use EntityContext for the first time, which in your example is not until after the call to SetInitializer.

You could consider forcing a call to the static initializer before making the SetInitializer call. For example, this should work:

using (var context = new EntityContext())
{
    Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>());
    context.Database.Initialize(true);
}

Upvotes: 1

Related Questions