c#EF DbContext - 从字符串动态生成对象

sar*_*and 2 c# entity-framework objectcontext

我想创建一个工厂类来返回DbContext表名将作为字符串传递的对象.数据库中有100多个表,每个表都有不同的结构/模式.

我们的想法是通过tableNamestring在将在EF返回对象,我们可以选择/更新这些记录的方法.我在一些文章中发现了这段代码,但是如何使用它却有些困惑:

public ObjectContext Context(EntityObject entity)
{
        var relationshipManager = ((IEntityWithRelationships)entity).RelationshipManager;
        var wrappedOwnerProperty = relationshipManager.GetType().GetProperty("WrappedOwner", BindingFlags.Instance | BindingFlags.NonPublic);
        var wrappedOwner = wrappedOwnerProperty.GetValue(relationshipManager);
        var contextProperty = wrappedOwner.GetType().GetProperty("Context");
        return (ObjectContext)contextProperty.GetValue(wrappedOwner);
}
Run Code Online (Sandbox Code Playgroud)

我不确定这是否是我需要的.还有什么我应该通过在EntityObject entity和我应该在哪里打发tableName

如果有任何其他方法可以实现相同的目的,请告诉我.

Eri*_*sch 6

一种简单的方法是使用DbContext.Set()方法,并根据字符串获取类型.

using (var db = new MyDbContext)
{
    string tableName = "ApplicationUser";
    var type = Assembly.GetExecutingAssembly()
       .GetTypes()
       .FirstOrDefault(t => t.Name == tableName);

    if(type != null)
    DbSet catContext = context.Set(type);    
}
Run Code Online (Sandbox Code Playgroud)

然而,这有一个缺点,那就是这是一个非泛型的DbSet(即它DbSet不是a DbSet<T>).

获取Generic DbSet(允许linq功能)的方法是执行以下操作:

using (var db = new IdentityDbContext())
{
    string tableName = "ApplicationUser";
    var type = Assembly.GetExecutingAssembly()
       .GetTypes().FirstOrDefault(t => t.Name == tableName);

    var method = db.GetType().GetMethods()
       .First(x => x.IsGenericMethod && x.Name == "Set");

    MethodInfo generic = method.MakeGenericMethod(type);
    var set = generic.Invoke(db, null);
}
Run Code Online (Sandbox Code Playgroud)

当然set在这里是一个对象,你必须以某种方式抛出它,这仍然是问题的一部分.

当它归结为它时,如果你不打算使用静态编译类型,你将不得不继续处理反射,特别是当你有通用类型来处理时(例如DbSet<T>,等等).您必须在某些时候将它们转换为静态类型以调用方法,或继续执行MethodInfo.Invoke.

另一个选择是使用动态,但你不能使用动态与c#扩展方法(没有强制转换为具体类型),所以你回到了没有Linq支持的同一条船上.

通过反射使用Linq是一个巨大的痛苦.

说实话,如果你有100个类,我只需咬紧牙关并编写硬编码类型,或使用代码生成器为你做CodeSmith.