2014-03-30 36 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確實不是建立在繼承模型之上的,也不是人們期望的(也許是出於很好的理由)。從長遠來看,它可能更好,不具有繼承性,並且具有單個上下文,即使它在開始時意味着一些代碼重複。