通过实体类名动态获取 DbSet<T>

San*_*oud 5 c# system.reflection entity-framework-core asp.net-core

我正在尝试使用它的名称动态System.Reflections获取DbSet<T>

我现在有的是:

  • DbSet
  • 所述DbSetType存储在可变

在尝试使用该dbcontext.Set<T>()方法时,我面临的问题出现了,因为(这些是我迄今为止的尝试):

  • 当我尝试分配给<T>my 时DbSet Type,它会引发以下编译错误:

    “XXX 是一个变量,但像类型一样使用”

  • 如果我尝试使用两种Extension方法,您将在我的代码下面找到(我为了设法弄一本制作IQueryable<T>),它返回一个IQueryable<object>,不幸的是不是我期待的,因为当然,当我尝试用进一步的反射操作它,它缺少原始类具有的所有属性......

我究竟做错了什么?我怎样才能得到一个DbSet<T>

我的代码如下,当然,如果您需要更多信息、说明或代码片段,请告诉我。

我的控制器的方法

public bool MyMethod (string t, int id, string jsonupdate)
{
    string _tableName = t;
    Type _type = TypeFinder.FindType(_tableName); //returns the correct type

    //FIRST TRY
    //throws error: "_type is a variable but is used like a type"
    var tableSet = _context.Set<_type>();  

    //SECOND TRY
    //returns me an IQueryable<object>, I need an IQueryable<MyType>
    var tableSet2 = _context.Set(_type);  

    //THIRD TRY
    //always returns me am IQueryable<object>, I need an IQueryable<MyType>
    var calcInstance = Activator.CreateInstance(_type);
    var _tableSet3 = _context.Set2(calcInstance);

    //...
}
Run Code Online (Sandbox Code Playgroud)

ContextSetExtension

public static class ContextSetExtension
{ 
    public static IQueryable<object> Set(this DbContext _context, Type t)
    {
        var res= _context.GetType().GetMethod("Set").MakeGenericMethod(t).Invoke(_context, null);
        return (IQueryable<object>)res;
    }


    public static IQueryable<T>Set2<T>(this DbContext _context, T t) 
    {
        var typo = t.GetType();
        return (IQueryable<T>)_context.GetType().GetMethod("Set").MakeGenericMethod(typo).Invoke(_context, null);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑添加TypeFinder的内部代码。
简而言之,此方法与 相同Type.GetType,但在所有生成的程序集上搜索 Type

public class TypeFinder
{

    public TypeFinder()
    {
    }
    public static Type FindType(string name)
    {


        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
        var result = (from elem in (from app in assemblies
                                        select (from tip in app.GetTypes()
                                                where tip.Name == name.Trim()
                                                select tip).FirstOrDefault())
                      where elem != null
                      select elem).FirstOrDefault();

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

根据评论中的要求更新,这是具体情况:

在我的数据库中,我有一些非常相似的表,所以我的想法是创建一个动态表更新方法,这对每个表都有好处,只需将表名,行的 ID 传递给这个方法要更新和包含要更新的数据的 JSON。
因此,简而言之,我将对输入中作为 DbSet 类型给出的表执行一些更新,ID==id使用包含在 JSON 中的数据更新输入中的行,这些数据将在 X 类型的对象中解析(与 dbset 相同) / 进入字典。

在伪代码中:

public bool MyMethod (string t, int id, string jsonupdate)
{
    string _tableName = t;
    Type _type = TypeFinder.FindType(_tableName); //returns the correct type

    //THIS DOESN'T WORKS, of course, since as said above:
    //<<throws error: "_type is a variable but is used like a type">>
    var tableSet = _context.Set<_type>();  

    //parsing the JSON
    var newObj = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonupdate, _type);

    //THIS OF COURSE DOESN'T WORKS TOO
    //selecting the row to update:
    var toUpdate = tableSet.Where(x => x.Id == id).FirstOrDefault();

    if(toUpdate!=null)
    {

       var newProperties = newObj.GetType().GetProperties();
       var toUpdateProperties = toUpdate.GetType().GetProperties();

       foreach(var item in properties)
       {
           var temp = toUpdateProperties.Where(p => p.Name==item.Name)
           {
              //I write it really in briefand fast, without lots of checks.
              //I think this is enough, I hope
              temp.SetValue(toUpdate, item.GetValue());
           }
       }

       _context.SaveChanges();
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

Cha*_*nte -1

编辑:测试并工作:

public async Task<bool> MyMethod(string _type)
{
    Type type = Type.GetType(_type);

    var tableSet = _context.Set(type);

    var list = await db.ToListAsync();

    // do something
}

// pass the full namespace of class
var result = await MyMethod("Namespace.Models.MyClass")
Run Code Online (Sandbox Code Playgroud)

重要提示:您的 DbContext 需要声明 DbSet 才能工作!

public class MyContext : DbContext
{
    public DbSet<MyClass> MyClasses { get; set; }
}
Run Code Online (Sandbox Code Playgroud)