多级派生的EF DataContext

时间:2014-03-30 17:25:30

标签: c# asp.net-mvc entity-framework asp.net-mvc-5

我们说我有一个基础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
    }
}

我尝试创建一个派生的datacontext,只需要几个附加集:

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

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

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

我使用SimpleInjector并注册上下文(在服务中使用),如下所示:

container.RegisterPerWebRequest<DerivedContext, DerivedContext>();

这样,只创建BaseContext个表。

如果我加上这个:

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

然后创建派生集,但初始化程序不会运行。

我错过了什么?做这样的事情的正确模式是什么?

1 个答案:

答案 0 :(得分:0)

所以这似乎有效,并且不涉及复制派生类中的所有内容:

// 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());
    }
}

所以这样可以保持干燥和清洁。由于某种原因,我仍然无法摆脱肮脏的感觉。

坐了一段时间后,我可以验证这种方法是否有效。但是,EF确实不是为了考虑继承模型,而是人们所期望的(可能是有充分理由的)。从长远来看,它可能更好,没有继承并且只有一个上下文,即使它意味着一些代码重复开始。