带有代码优先的EntityFramework:在运行时检测实体类型
本文关键字:运行时 检测 实体 类型 EntityFramework 代码 | 更新日期: 2023-09-27 18:13:22
当使用代码优先方法的EntityFramework时,您通常从DbContext派生并为您拥有的所有实体类型创建DbSet属性。
我不能这样做,因为我的软件可以与模块一起使用,这些模块提供了编译时不知道的新实体类型。
所以我想确定运行时可用实体类型的列表。
我得到了它的部分工作与这段代码:
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
实现。如果库静态地不知道彼此,那么它们就没有静态的方法来拥有到其他库中的类的导航属性。然后你可以有独立的DbContexts
,每个库一个。如何在主代码中使用它们?这取决于你的实现,但我想你可以弄清楚。
当库相互引用时,不能有循环,因此,它们形成逻辑拓扑排序,例如,如果库A和B引用C,如果它不使用自己的实体,则可以在A和B中有DbContexts
而不在C中。
传统上,在EF中没有什么可以阻止您这样做,除非您需要迁移。现在EF支持同一数据库上不同DbContexts
的迁移