动态获得DbSet< T>。按实体类名称 [英] Dynamically get a DbSet<T> by Entity class name

查看:150
本文介绍了动态获得DbSet< T>。按实体类名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to use System.Reflections to get a DbSet<T> dynamically from its name.

我现在得到的是:


  • DbSet 名称

  • DbSet Type 存储在变量上

  • The DbSet name
  • The DbSet's Type stored on a variable

我在尝试使用时遇到的问题dbcontext.Set< T>()方法,因为(到目前为止,这是我的尝试):

The issue I'm facing comes out when trying to use the dbcontext.Set<T>() method, since (these are my tries so far):


  • 何时我尝试将 DbSet Type < T> >,它会引发以下编译错误:

  • When I try to assign to <T> my DbSet Type, it throws me the following compilation error:

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

"XXX is a variable but is used like a type"


  • 如果我尝试同时使用下面的 Extension 方法,您将在下面的代码中找到它们(我为了尝试获取 IQueryable< T> ),它返回 IQueryable< object> ,不幸的是我不是上午寻找,当然,因为当我尝试通过进一步的思考来操作它时,它缺少原始类具有的所有属性……

  • If I try with using both the Extension methods that you will find below in my code (which I made in order to try to get an IQueryable<T>), it returns a IQueryable<object>, which unfortunately is not what I am looking for, since of course when I try to manipulate it with further Reflections, it lacks of all the properties that the original class has…
  • 我在做什么错?如何获得 DbSet< T>

    What am I doing wrong? How can I get a DbSet<T>?

    我的代码如下,但是,当然,让我知道您是否需要更多信息,说明或代码段。

    My code is the following, but of course, let me know if you need more infos, clarifications or code snippets.

    我的控制器方法

    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);
    
        //...
    }
    

    班级 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);
        }
    }
    

    编辑已添加 TypeFinder 的内部代码。

    简而言之,该方法的作用与 Type.GetType 相同,但是在所有生成的程序集上搜索Type

    EDIT Added TypeFinder's inner code.
    In brief, this method does the same of Type.GetType, but searches Type on ALL the generated assemblies

    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;
        }
    }
    

    更新注释,这是特定情况:

    UPDATE as requested in the comments, here's the specific case:

    在我的数据库中,我有一些表彼此之间非常相似,因此,其目的是创建动态表更新该方法对每个表都适用,只需将表名,要更新的行的ID和包含要更新的数据的JSON传递给该方法。

    因此,简而言之,我将对输入中作为DbSet类型给出的表进行一些更新,使用输入中的 ID == id 来更新行。数据包含在JSON中,这些数据将在X类型的对象(与dbset相同)中解析/进入字典。

    In my DB i've got some tables which are really similar each other, so the idea was to create a dynamic table-update method which would be good for every table, just passing to this method the table name, the ID of the row to update and the JSON containing data to update.
    So, in brief, I would perform some updates on the table given in input as DbSet type, updating the row with ID==id in input with the data contained inside the JSON, which will be parsed inside an object of type X(the same of dbset)/into a dictionary.

    代码:

    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;
    }
    


    推荐答案

    returns me an IQueryable<object>, I need an IQueryable<MyType>
    

    嗯,那将永远无法工作。您的IQueryable不能为 IQueryable< MyType> 类型,因为这意味着编译器将需要知道 MyType 是什么,并且这是不可能的,因为本练习的重点是在运行时确定。

    Well, that will never work. Your IQueryable cannot be of type IQueryable<MyType>because that would mean the compiler would need to know what MyType is and that is not possible, because the whole point of this exercise is to decide that on runtime.

    也许知道这些对象是足够的实际上是 MyType

    Maybe it's enough to know that those objects are in fact instances of MyType?

    如果没有,我认为您已经将自己描绘在一个角落,试图弄清楚要使用哪种油漆才能摆脱困境。退后一步,这可能不是技术问题。 为什么,您需要这样做吗?为什么只有在运行时才知道类型,而在编译时才知道类型的冲突需求?

    If not, I think you have painted yourself into a corner here and you are trying to figure out what paint to use to get out of there. Take a step back, it's probably not a technical problem. Why do you need to do this? Why do you have the conflicting needs of knowing the type at runtime only and knowing it at compile time?

    您需要考虑一下需求,而不是技术细节。

    You need to think about your requirements, not about the technical details.

    这篇关于动态获得DbSet&lt; T&gt;。按实体类名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆