通過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屬性?
你的類型是動態的,所以你怎麼用這個'DbContext.Set()'?使用代碼進行配置可能很複雜,您的反射代碼很簡單,映射怎麼樣?是不是映射也是動態的?編譯時你的模型看起來是空的。所以我認爲你可以嘗試使用接受'DbCompiledModel'的構造函數來創建你的DbContext。 DbCompiledModel可以從'DbModel'的'Compile'方法獲得,該方法可以從'DbModelBuilder'的'Build'方法獲得。這意味着你從一個'DbModelBuilder'開始,隨時隨地創建一個實例。 –
Hopeless
這些類型不是在運行時創建的,它們在編譯相關程序集時只是未知的。這適用於可以與其他可以提供新實體類型的程序集一起使用的程序庫。至於映射,我還沒有想過。但是,謝謝,我將看看DbModelBuilder類。 –