Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding Shotgun Surgery with Database.SetInitializer

The canonical answer on where to put Database.SetInitializer calls is in Global.asax for web projects. I'm looking for another option.

We're using Entity Framework 4.3.1 with Code First. We write web services and WinForms applications, and typically put data access code (such as DbContexts) in shared libraries.

Currently, the constructors of our DbContext descendants look like this:

public PricingContext(string connectionString)
    : base(connectionString)
{
    Database.SetInitializer<PricingContext>(null);
}

95% of the time, that's the right default. 5% of the time (some integration tests, greenfield development, etc.) it's not.

If we move that code into the initialization (or configuration) of our services and applications, adding a new DbContext to a library involves Shotgun Surgery. All of these projects have to be updated, even if the library doesn't expose the context directly.

Optional arguments are one possibility:

public PricingContext(string connectionString,
    IDatabaseInitializer<PricingContext> databaseInitializer = null)
    : base(connectionString)
{
    Database.SetInitializer<PricingContext>(databaseInitializer);
}

Overriding the default strategy might involve passing the initializer through multiple layers, though.

We've also considered creating a reflection-based initializer that would set all contexts to a specific strategy.

What's the best practice?

like image 903
TrueWill Avatar asked Jul 12 '12 21:07

TrueWill


2 Answers

How about creating a DBContextBootstrapper class that you can instantiate in Global.asax of every project; which in its implementation sets initializer for every context.

This way if you add a new dbcontext you have to make change in the bootstrapper only, not in every project.

like image 68
Muhammad Hasan Khan Avatar answered Nov 15 '22 10:11

Muhammad Hasan Khan


EF 4.3 (and newer) also includes possibility to define initializer from configuration file so you will not need to set it in code at all but it will still require you to maintain multiple configs.

@Hasan's advice looks like the best solution for you.

like image 24
Ladislav Mrnka Avatar answered Nov 15 '22 12:11

Ladislav Mrnka