从类型中获取 DbSet

Posted

技术标签:

【中文标题】从类型中获取 DbSet【英文标题】:Get DbSet from type 【发布时间】:2015-12-14 03:54:37 【问题描述】:

我正在尝试为 MVC 6 应用程序制作通用表格查看器/编辑器。

我现在用

Context.GetEntityTypes();

向我返回表格列表。

现在我需要获取特定类型的数据。我目前的实现是:

// On my context
public IQueryable<dynamic> GetDbSetByType(string fullname)

    Type targetType = Type.GetType(fullname);

    var model = GetType()
        .GetRuntimeProperties()
        .Where(o =>
            o.PropertyType.IsGenericType &&
            o.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
            o.PropertyType.GenericTypeArguments.Contains(targetType))
        .FirstOrDefault();

    if (null != model)
    
        return (IQueryable<dynamic>)model.GetValue(this);
    

    return null;

在我的控制器中使用此代码

[HttpGet("requestedContext/requestedTable/data")]
public IActionResult GetTableData(string requestedContext, string requestedTable)

    var data = Request.Query;
    var context = GetContext(requestedContext);

    if (context == null)
    
        return new ErrorObjectResult("Invalid context specified");
    
    var entity = context.GetEntity(requestedTable);

    if (entity == null)
    
        return new ErrorObjectResult("Invalid table specified");
    

    var set = context.GetDbSetByType(entity.ClrType.AssemblyQualifiedName);

    if (set == null)
    
        return new ErrorObjectResult("Invalid table specified - DbSet could not be found");
    

    var start = Convert.ToInt32(data["start"].ToString());
    var count = Convert.ToInt32(data["length"].ToString());
    var search = data["search[value]"];

    return new ObjectResult(set.Skip(start).Take(count));

事实上,这将返回长度为count 和位置为start 的数据。但是我无法对IQueryable&lt;dynamic&gt; 的特定属性执行查询。

问题是:

    这似乎是一件微不足道的事情,所以我几乎可以肯定我错过了什么 - 这一定很容易做到。 如果不是 1,那么如何将我的 object set 转换回 DbSet&lt;T&gt; 以便执行查询?如果我设置断点并进行检查,我可以看到我的所有数据都放在那里。

注意:这是 EF7

附加信息:

    requestedTable 是完全限定类型 EG:&lt;mysystem&gt;.Models.Shared.Users

编辑 (2016/5/5)

我最终只是用纯 SQL 完成了这一切 - 如果有人确实设法让这个工作,请告诉我!

【问题讨论】:

如果 GetType() 实际上得到了你的类型(也就是说,引用的类型实际上是在可用的程序集中定义的)并且是在 dbContext 的集合中注册的类名,你不能只使用上下文。设置?这是一个 DbSet 并继承了 IQueryable 【参考方案1】:

使用泛型方法和DbContext.Set&lt;TEntity&gt;() 会更简单。你可以像这样在运行时创建一个泛型方法:

public IActionResult GetTableData(string requestedContext, string requestedTable)

    var context = GetContext(requestedContext);

    if (context == null)
    
        return new ErrorObjectResult("Invalid context specified");
    
    var entity = context.GetEntity(requestedTable);

    if (entity == null)
    
        return new ErrorObjectResult("Invalid table specified");
    

    var boundMethod = s_getTableDataMethodInfo.MakeGenericMethod(entity.ClrType);
    return boundMethod.Invoke(this, new object[]  context ) as IActionResult;


private static readonly MethodInfo s_getTableDataMethodInfo
    = typeof(MyController).GetTypeInfo().GetDeclaredMethod("GetTableDataForEntity");

private IActionResult GetTableDataForEntity<TEntity>(DbContext context)
    where TEntity : class

    var data = Request.Query;
    var start = Convert.ToInt32(data["start"].ToString());
    var count = Convert.ToInt32(data["length"].ToString());
    var search = data["search[value]"];

    return new ObjectResult(context.Set<TEntity>().Skip(start).Take(count));

【讨论】:

以上是关于从类型中获取 DbSet的主要内容,如果未能解决你的问题,请参考以下文章

无法为“ApplicationUser”创建 DbSet,因为此类型未包含在上下文模型中

类型类的 DbSet 属性返回 null

找不到源类型“System.Data.Entity.DbSet”的查询模式的实现

为源类型“DbSet<>”找到了查询模式的多个实现。对“在哪里”的模棱两可的呼唤

C#,MVC3,如何将非泛型 DBSet 与运行时定义的类型一起使用?

为啥类 DBSet 的 AsQueryable() 不在 MSDN 文档中?