首页 文章

使用Code First的EntityFramework:在运行时检测实体类型

提问于
浏览
1

将EntityFramework与Code First方法一起使用时,通常从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 永远不会被调用 . 我必须在我的 class 添加一个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,因此一切都按预期工作 .

Question: 有没有办法在不向我的类添加公共DbSet属性的情况下实现相同的功能?

1 回答

  • 1

    你能不能以更加静态的方式解决问题?例如,每个库也可以提供自己的 DbContext 实现 . 如果库静态地不知道彼此,那么它们就没有静态的方法来为其他库中的类提供导航属性 . 然后你可以拥有独立的 DbContexts ,每个库一个 . 如何在主代码中使用它们?这取决于你的实现,但我想你可以搞清楚 .

    当库互相引用时,可能没有循环,因此,它们形成逻辑拓扑排序 . 例如,如果库A和B引用C,则可以在A和B中使用 DbContexts 而不在C中,如果它不使用它自己的实体 .

    传统上,除非您需要迁移,否则没有任何东西可以阻止您在EF中执行此操作 . 现在,对于同一数据库中的不同 DbContexts ,EF supports迁移 .

相关问题