2014-03-30 39 views
0

比方说,我有一个基础的datacontext:多级衍生EF的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“ s表被创建。

如果我补充一点:

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

然后获得创建派生套,但初始化不运行。

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

+0

也许发生这种情况是因为您实现了'IDatabaseInitializer '而不是'IDatabaseInitializer '? – Steven

+0

我也在想。事情是,我不能(或者更不愿意)改变'IDatabaseInitializer',因为其他人只依赖** BaseContext。但是,是否有一个干净的模式来实现这种事情? – Mrchief

+3

从我们观察到的情况来看,ef并不关心你的上下文是否从另一个上下文继承 - 两个不同的上下文类型是两个不同的上下文,并且初始化必须精确地定义在你想要执行的类型上。 –

回答

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确实不是建立在继承模型之上的,也不是人们期望的(也许是出于很好的理由)。从长远来看,它可能更好,不具有继承性,并且具有单个上下文,即使它在开始时意味着一些代码重复。