【问题标题】:Net Core: Add to DbSet<Table> from a String TypeNet Core:从字符串类型添加到 DbSet<Table>
【发布时间】:2020-11-22 20:15:12
【问题描述】:

如何获取 Entity Framework Core DBSet,其中输入是字符串变量名?尝试获取下面的 DBSet 类型,但改为接收 IQueryable。

上一个答案在 Net Core 3.0 中不起作用

资源:Getting DbSet<MyTable> from a string

How do I select correct DbSet in DbContext based on table name

var tableString = "Product";
var tableType = Type.GetType(tableString, false, true);
if (tableType == null)
{
    throw new ArgumentException($"Invalid table type: {tableType }.");
}

_dbContext.Set<Product>().Add({ProductId = 5, ProductName = "Furniture"});  // Adding to a DbSet, This will work !

_dbContext.Set(tableType).Add({ProductId = 5, ProductName = "Furniture"});  // Cannot add to this,  since this is actually an IQueryable

错误:“IQueryable”不包含“Add”的定义,并且找不到接受“IQueryable”类型的第一个参数的可访问扩展方法“Add”(您是否缺少 using 指令或程序集引用?)

【问题讨论】:

    标签: c# entity-framework asp.net-core .net-core entity-framework-core


    【解决方案1】:

    DbContext 中似乎没有方法从 .NET Core 3.0 中的类型或字符串中获取 DbSet。

    https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext?view=efcore-3.0

    作为一种解决方法,你可以试试这个,

    var dbSet = (DbSet<Product>)_dbContext.GetType().GetMethod("Set").MakeGenericMethod(tableType).Invoke(_dbContext, null); 
    

    【讨论】:

    • 嗨,您仍在使用 在答案中硬编码,因此它不起作用 (DbSet)_dbContext.GetType
    • 是的,没错。那么如何在没有硬编码的情况下创建产品呢?如果答案是使用反射来动态创建产品,那为什么不能直接在 DbContext 上使用 Add 方法呢?
    • “product”作为变量字符串输入,只能这样看
    【解决方案2】:

    首先,你需要一个扩展

    using Microsoft.EntityFrameworkCore;
    
    namespace MyProject.Utils
    {
        public static class MyExtensions
        {
            public static object Set(this DbContext _context, Type t)
            {
                return _context.GetType().GetMethod("Set").MakeGenericMethod(t).Invoke(_context, null);
            }
        }
    }
    

    然后你可以试试这个代码。

    var tableName = "UserInfo";
    string tableFullName = $"Qc.Data.Domain.{tableName}";
    string domainAssembly = "Qc.Data";
    string assemblyQualifiedName = Assembly.CreateQualifiedName(domainAssembly, tableFullName);
    var entityType = Type.GetType(assemblyQualifiedName);
    
    using (var dbContext = new MyDbContext())
    {
        var dbSet = dbContext.Set(entityType);
    
        var entityJson = Newtonsoft.Json.JsonConvert.SerializeObject(new
        {
            Avatar = "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png",
            Gender = UserGender.Man,
            NickName = "UserName",
            UniqueId = Guid.NewGuid().ToString("N"),
        });
    
        var model = Newtonsoft.Json.JsonConvert.DeserializeObject(entityJson, entityType);
    
    
        var methods = dbSet.GetType().GetMethods();
    
        MethodInfo AddMethod = dbSet.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance)
            .FirstOrDefault(m => m.Name == "Add" && m.GetParameters().Count() == 1);
    
        object retVal = AddMethod.Invoke(dbSet, new object[] { model });
    
        dbContext.SaveChanges();
    }
    

    我试了两个小时,希望对你有帮助。

    【讨论】:

    • 您好,我们需要的就是这个,谢谢!随意测试和编辑您的答案 var entityJson = Newtonsoft.Json.JsonConvert.SerializeObject(test); var model = Newtonsoft.Json.JsonConvert.DeserializeObject(entityJson, tableType);
    • 您也可以使用 AutoMapper。将对象转换为您的数据库实体,如果对您有帮助,请单击向上箭头,谢谢。
    • 我刚刚添加了对我有用的简化更改,反序列化和序列化,请随意尝试
    猜你喜欢
    • 2020-02-01
    • 2016-12-12
    • 2019-06-21
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多