简体   繁体   中英

Multi-level derived EF DataContext

Let's say I have a base datacontext:

public class BaseContext : DbContext {
    public DbSet<User> Users { get; set; }

    public BaseContext(): base("default")
    {
        Database.SetInitializer(new BaseContextInitializer());
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.Add(new UserConfiguration());
    }
}


public class BaseContextInitializer : IDatabaseInitializer<BaseContext>
{
    private static readonly Lazy<bool> ShouldInitializeDatabase = new Lazy<bool>(() =>
                                                           string.IsNullOrWhiteSpace(
                                                               ConfigurationManager.AppSettings[
                                                                   "InitializeDatabase"]));

    public void InitializeDatabase(BaseContext context)
    {
        if (!ShouldInitializeDatabase.Value) return;

        bool dataBaseExists;
        using (new TransactionScope(TransactionScopeOption.Suppress))
            dataBaseExists = context.Database.Exists();

        if (dataBaseExists)
        {
            try
            {
                if (context.Database.CompatibleWithModel(true))
                    return;
                context.Database.Delete();

            }
            catch (NotSupportedException)
            {
                context.Database.Delete();

            }
        }

        context.Database.Create();
        context.Database.ExecuteSqlCommand("alter table Users add constraint UniqueUserEmail unique (Email)");

        Seed(context);

    }

    protected virtual void Seed(BaseContext context)
    {
        // seeding code
    }
}

And I'm trying to create a derived datacontext with few additional sets:

public class DerivedContext : BaseContext {
    public DbSet<Admin> Admins { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.Add(new AdminConfiguration());
    }
}

I'm using SimpleInjector and registering contexts (for usage in services) like this:

container.RegisterPerWebRequest<DerivedContext, DerivedContext>();

With this, only BaseContext 's tables are created.

If I add this:

container.RegisterPerWebRequest<BaseContext, DerivedContext>();
container.RegisterPerWebRequest<DerivedContext, DerivedContext>();

then the derived sets get created but the initializer doesn't run.

What am I missing? And what is the proper pattern to do something like this?

So this seems to be working and doesn't involve duplicating everything in derived classes:

// make it generic
public class BaseContextInitializer<T> : IDatabaseInitializer<T>
{
   // ...
   public void InitializeDatabase(T context) 
   {
        // ...
   }
}

    // now pass the derivedcontext in the derived initializer
public class DerivedContextInitializer : BaseContextInitializer<DerivedContext>
{
    // overrides etc. etc.  
} 


    // set the initializer to be the derived one
public class DerivedContext : BaseContext {
    public DbSet<Admin> Admins { get; set; }

    public DerivedContext(): base("default")
    {
        Database.SetInitializer(new DerivedContextInitializer());
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.Add(new AdminConfiguration());
    }
}

So this keeps thing somewhat DRY and clean. I still can't shake off the dirty feeling for some reason.

After sitting on it for sometime, I can verify that this approach works. However, EF really isn't built to factor in inheritance models as well as one would expect (maybe for good reasons). Its probably better in long run to not have inheritance and have a single context, even if it means some code duplication in beginning.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM