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

标签 c# asp.net-core entity-framework-core system.reflection

我正在尝试使用 System.Reflections获得 DbSet<T>从它的名字动态。

我现在有的是:

  • DbSet姓名
  • DbSetType存储在变量

  • 我在尝试使用 dbcontext.Set<T>() 时遇到的问题方法,因为(这些是我迄今为止的尝试):
  • 当我尝试分配给 <T> 时我的 DbSet Type ,它向我抛出以下编译错误:

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

  • 如果我尝试同时使用 Extension您将在我的代码(我为了尝试获得 IQueryable<T> 而编写的)中找到的方法,它返回一个 IQueryable<object> ,不幸的是,这不是我想要的,因为当然当我尝试用进一步的反射来操作它时,它缺少原始类具有的所有属性......

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

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

    我的 Controller 的方法 :
    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);
    
        //...
    }
    

    类(class)上下文集扩展
    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);
        }
    }
    

    编辑 已添加 打字机 的内码。
    简而言之,此方法与 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;
        }
    }
    

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

    在我的数据库中,我有一些非常相似的表,所以我的想法是创建一个动态表更新方法,这对每个表都有好处,只需将表名,行的 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;
    }
    

    最佳答案

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

    好吧,那永远行不通。您的 IQueryable 不能是 IQueryable<MyType> 类型因为那意味着编译器需要知道什么 MyType是的,那是不可能的,因为本练习的重点是在运行时决定这一点。

    也许知道这些对象实际上是 MyType 的实例就足够了。 ?

    如果没有,我想你已经把自己画到了一个角落里,你正试图弄清楚用什么油漆才能离开那里。退后一步,这可能不是技术问题。为什么需要这样做?为什么只在运行时知道类型和在编译时知道类型存在冲突?

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

    关于c# - 通过实体类名动态获取 DbSet<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52721697/

    相关文章:

    asp.net-core - ASP.Net 核心中的持久 session

    c# - .NET Core EF 2.1 脚手架-数据库优先-如何添加更多表

    c# - 如何将 EF Core 2.2.4 数据库与 Asp.Net Core 2.1 项目结合使用

    c# - 从 Windows 窗体过渡到 WPF

    javascript - 有没有一种简单的方法可以将秒数转换为 ISO 8601 格式以用于 schema.org 视频元数据?

    c# - ASP.NET MVC 1.0 + 单声道 2.4

    c# - 内部不能有带有动态代码的 [Authorize()]

    c# - 获取写入文件时字符串占用的大小(以字节为单位)?

    docker - .NET Core 项目的 AppSettings 未在 Docker 容器中覆盖

    c# - 在 Entity Framework Core 中强制不区分大小写的 String.Contains