EF Core 2.0 中的动态访问表
Posted
技术标签:
【中文标题】EF Core 2.0 中的动态访问表【英文标题】:Dynamically access table in EF Core 2.0 【发布时间】:2018-06-11 00:41:35 【问题描述】:我正在使用System.Linq.Dynamic.Core
将 lambda 表达式动态添加到 EF 中的查询中。
我还希望能够按名称选择表。我找到了这个答案:
https://***.com/a/28101268/657477
但它不适用于 asp.net core 2.0。我不能使用DbSet
我必须使用DbSet<TEntity>
它在错误消息中说。
我希望能够做到db.GetTable("Namespace.MyTable").Where(...)
我该怎么做?
【问题讨论】:
TEntity 不是通用的吗? 看看这里***.com/a/44143131/2946329 【参考方案1】:首先您需要从名称中获取实体的类型(如果您有类型,则直接使用它)。您可以为此使用反射,但 EF Core 的正确方法可能是使用 FindEntityType
方法。
一旦有了类型,问题就是如何获取对应的DbSet<T>
。 EF Core 目前不提供类似于 EF6 的非泛型 Set(Type)
方法,主要是因为没有非泛型 DbSet
类。但是您仍然可以通过使用一些 EF Core 内部来获得对应的 DbSet<T>
为 IQueryable
:
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Internal;
namespace Microsoft.EntityFrameworkCore
public static partial class CustomExtensions
public static IQueryable Query(this DbContext context, string entityName) =>
context.Query(context.Model.FindEntityType(entityName).ClrType);
public static IQueryable Query(this DbContext context, Type entityType) =>
(IQueryable)((IDbSetCache)context).GetOrAddSet(context.GetDependencies().SetSource, entityType);
或者(最好)通过反射调用通用的Set<T>
方法:
using System;
using System.Linq;
using System.Reflection;
namespace Microsoft.EntityFrameworkCore
public static partial class CustomExtensions
public static IQueryable Query(this DbContext context, string entityName) =>
context.Query(context.Model.FindEntityType(entityName).ClrType);
static readonly MethodInfo SetMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set), Type.EmptyTypes);
public static IQueryable Query(this DbContext context, Type entityType) =>
(IQueryable)SetMethod.MakeGenericMethod(entityType).Invoke(context, null);
在这两种情况下,您都可以使用如下内容:
db.Query("Namespace.MyTable").Where(...)
或
db.Query(typeof(MyTable)).Where(...)
【讨论】:
这很好用。感谢您帮助我,我真的很努力解决这个问题。 我遇到了这个方法的问题。我无法包含嵌套实体,因为 Include() 没有定义。有什么办法吗? 在我的情况下,IQueryable 不包含 Where 的定义 :( @mzain 它没有。所有 LINQ 扩展方法都是为IQuerabley<T>
而不是为 IQueryable
定义的。因此,虽然答案显示了如何通过Type
检索DbSet
,但返回的结果不能直接使用。如果事先知道T
的类型,最好使用Set<T>()
方法。
@Guerrilla 这个效果如何?如果没有通用类型,您将无法在 Iqueriable 上执行 .Where。【参考方案2】:
EF Core 不再有非通用的Set
方法,但是这个扩展类使得使用动态 linq 基于字符串查询表变得容易。将 TableTypeDictionary
视为 Dictionary<string, Type>
映射 DbSet 类型及其类型名称。
public static class DbContextExtensions
public static IQueryable<Object> Set(this DbContext _context, Type t)
return (IQueryable<Object>)_context.GetType().GetMethod("Set").MakeGenericMethod(t).Invoke(_context, null);
public static IQueryable<Object> Set(this DbContext _context, String table)
Type tableType;
//One way to get the Type
tableType = _context.GetType().Assembly.GetExportedTypes().FirstOrDefault(t => t.Name == table);
//The Second way, get from the dictionary which we've initialized at startup
tableType = TableTypeDictionary[table];
//The third way, works only if 'table' is an 'assembly qualified type name'
tableType = Type.GetType(table);
IQueryable<Object> objectContext = _context.Set(tableType);
return objectContext;
用法:
IQueryable<Object> query = db.Set("TableName");
//or if you're using the third way:
query = db.Set(MyTable.GetType().AssemblyQualifiedName);
// Filter against "query" variable below...
List<Object> result = query.ToList();
// or use further dynamic Linq
IQueryable<Object> query = db.Set("TableName").Where("t => t.TableFilter == \"MyFilter\"");
【讨论】:
TableTypeDictionary ? 方法 'Set' 没有重载需要 1 个参数IQueryable<Object>
没有.Where(string)
的实现。
@HGMamaci 我已经编辑了答案以涵盖您的问题。
不再适用于 ef core6以上是关于EF Core 2.0 中的动态访问表的主要内容,如果未能解决你的问题,请参考以下文章
Azure Functions .NET Core 中的 EF Core 2.0 连接字符串