2015-09-19 36 views
1

通過Code First方法使用EntityFramework時,通常從DbContext派生併爲所有實體類型創建DbSet屬性。帶有Code First的EntityFramework:在運行時檢測實體類型

我不能這樣做,因爲我的軟件可以用於提供在編譯時不知道的新實體類型的模塊。

所以我想在運行時確定可用實體類型的列表。

我得到了它部分地使用此代碼的工作:

public class MyDbContext: DbContext 
{ 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     var entityMethod = typeof(DbModelBuilder).GetMethod("Entity"); 

     foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) 
     { 
      // Register all types that derive from ModelBase as entity types 
      var entityTypes = assembly 
       .GetTypes() 
       .Where(t => t.IsSubclassOf(typeof(ModelBase))); 

      foreach (var type in entityTypes) 
      { 
       entityMethod.MakeGenericMethod(type) 
        .Invoke(modelBuilder, new object[] { }); 
      } 
     } 
    } 
} 

然而,當我這樣做,OnModelCreating不會被調用。我必須添加一個DbSet給我的班級。我甚至不能使DbSet私有或內部,它必須是公開的,這使得它一個醜陋的解決方法:

public DbSet<DummyType> DummyTypes { get; set; } 

public MyDbContext(string connectionName): 
    base(connectionName) 
{ 
    // Force initialization to make sure OnModelCreating 
    // has been called after leaving the constructor 
    DummyTypes.Count(); 
} 

在添加此解決方案,我可以通過調用DbContext.Set<EntityType>()方法訪問DbSets,所以一切正常如預期。

問題:有沒有一種方法可以實現相同的事情,而不需要向我的類添加公共DbSet屬性?

+1

你的類型是動態的,所以你怎麼用這個'DbContext.Set ()'?使用代碼進行配置可能很複雜,您的反射代碼很簡單,映射怎麼樣?是不是映射也是動態的?編譯時你的模型看起來是空的。所以我認爲你可以嘗試使用接受'DbCompiledModel'的構造函數來創建你的DbContext。 DbCompiledModel可以從'DbModel'的'Compile'方法獲得,該方法可以從'DbModelBuilder'的'Build'方法獲得。這意味着你從一個'DbModelBuilder'開始,隨時隨地創建一個實例。 – Hopeless

+0

這些類型不是在運行時創建的,它們在編譯相關程序集時只是未知的。這適用於可以與其他可以提供新實體類型的程序集一起使用的程序庫。至於映射,我還沒有想過。但是,謝謝,我將看看DbModelBuilder類。 –

回答

1

難道你不能以更靜態的方式解決你的問題嗎?例如,每個庫也可以提供它自己的DbContext實現。如果庫靜態地不知道對方,那麼它們就沒有靜態的方式讓它們具有導航屬性到其他庫中的類。然後你可以有獨立的DbContexts,每個圖書館一個。如何在你的主代碼中使用它們?這取決於你的實現,但我想你可以弄明白。

當庫彼此相互引用時,不會出現循環,因此它們形成邏輯拓撲排序。例如,如果庫A和B引用C,則在A和B中可以有DbContexts,如果是不使用自己的實體。

傳統上,沒有什麼能夠阻止你在EF中這樣做,除非你需要遷移。現在EF supports遷移到同一數據庫上的不同DbContexts

+1

我很猶豫要使用多個DbContext實例,因爲我想避免在多個不同的位置調用SaveChanges和類似的東西,但看起來你是對的。解決這些問題比我想的要容易。 –

相關問題