C# 从在字符串定义字段上筛选的字符串定义的表名中获取数据
我试图根据一个值数组中的动态字段名返回动态类型的Where筛选表的内容 以下是我到目前为止的情况:C# 从在字符串定义字段上筛选的字符串定义的表名中获取数据,c#,asp.net-mvc,entity-framework,linq,C#,Asp.net Mvc,Entity Framework,Linq,我试图根据一个值数组中的动态字段名返回动态类型的Where筛选表的内容 以下是我到目前为止的情况: public JsonResult GetRelationShips(string linkingTable, string idField, int[] ids) { var tableType = typeof(context).GetProperty(linkingTable); var entityTable = tableType.GetValu
public JsonResult GetRelationShips(string linkingTable, string idField, int[] ids)
{
var tableType = typeof(context).GetProperty(linkingTable);
var entityTable = tableType.GetValue(db) as IQueryable;
var method = typeof(List<int>).GetMethod("Contains");
var eParam = Expression.Parameter(tableType.PropertyType.GetGenericArguments()[0]);
var call = Expression.Call(Expression.Constant(ids.ToList()), method, Expression.Property(eParam, idField));
var func = typeof(Func<,>);
var genericFunc = func.MakeGenericType(tableType.PropertyType.GetGenericArguments()[0], typeof(bool));
var lambda = Expression.Lambda(genericFunc, call, eParam);
var results = typeof(System.Linq.Enumerable).GetMethods().Where(x => x.Name == "Where").First().Invoke(db, new object[] { lambda });
return Json(results);
}
公共JsonResult GetRelationShips(字符串链接表、字符串idField、int[]ID)
{
var tableType=typeof(context).GetProperty(linkingTable);
var entityTable=tableType.GetValue(db)作为IQueryable;
var method=typeof(List).GetMethod(“Contains”);
var eParam=Expression.Parameter(tableType.PropertyType.GetGenericArguments()[0]);
var call=Expression.call(Expression.Constant(ids.ToList()),方法,Expression.Property(eParam,idField));
var func=类型化(func);
var genericFunc=func.MakeGenericType(tableType.PropertyType.GetGenericArguments()[0],typeof(bool));
var lambda=Expression.lambda(genericFunc,call,eParam);
var results=typeof(System.Linq.Enumerable).GetMethods().Where(x=>x.Name==“Where”).First().Invoke(db,新对象[]{lambda});
返回Json(结果);
}
最后一行给了我一个错误:
不能对ContainsGenericParameters为true的类型或方法执行后期绑定操作
老实说,今天下午我是从互联网上的片段拼凑而成的。我不知道我在这里做什么,这对我来说是新的,我渴望学习。为了避免SQL注入,项目的其余部分完全是Linq,所以我将继续努力。我也在学习泛型类型,但我不知道如何在这里使用它们。这一行代码中有很多缺陷:
var results = typeof(System.Linq.Enumerable).GetMethods().Where(x => x.Name == "Where").First().Invoke(db, new object[] { lambda });
- 正在尝试调用
而不是可枚举的.Where
。这将导致检索整个表数据并在内存中而不是在数据库端执行过滤可查询的.Where
- 试图调用可能错误的方法
有2个重载,未定义反射将首先返回哪个重载其中
- 试图调用泛型方法定义,导致出现异常。您必须首先使用
构造一个泛型方法并调用它MakeGenericMethod
- 试图通过反射调用静态泛型扩展方法,就像调用实例方法一样。相反,您应该将
作为第一个参数传递给null
,并将Invoke
作为第二个参数传递newobject[]{entityTable,lambda}
IQueryable results = Queryable.Where((dynamic)entityTable, (dynamic)lambda);
使用以下重载可以简化整个代码:
public static MethodCallExpression Call(
Type type,
string methodName,
Type[] typeArguments,
params Expression[] arguments);
这对于“调用”静态泛型扩展方法非常有用:
var query = (IQueryable)db.GetType().GetProperty(linkingTable).GetValue(db);
// e =>
var entity = Expression.Parameter(query.ElementType, "e");
// ids.Contains(e.idField)
// = Enumerable<int>.Contains(ids, e.idField)
var containsCall = Expression.Call(
typeof(Enumerable),
nameof(Enumerable.Contains),
new Type[] { typeof(int) },
Expression.Constant(ids),
Expression.Property(entity, idField)
);
// e => ids.Contains(e.idField)
var predicate = Expression.Lambda(containsCall, entity);
// query = query.Where(predicate);
query = Queryable.Where((dynamic)query, (dynamic)predicate);
我提供所有这些只是因为你说你渴望学习。处理此类任务(而不是重新发明轮子)的最简单方法是使用一些第三方软件包。例如,对于包,整个代码将是:
var query = ((IQueryable)db.GetType().GetProperty(linkingTable).GetValue(db))
.Where($"@0.Contains({idField})", ids);
谢谢你,看起来不错。我今天没有时间做任何事。一个问题;System.Linq.Dynamic选项仍然是SQL注入的证明吗?它基本上是Linq
IQueryable
查询转换器的字符串,因此根本不涉及SQL或任何类型的可执行代码。对动态Linq:var query=((IQueryable)db.GetType().GetProperty(linkingTable).GetValue(db))。其中($“@0.Contains(outerIt.{idField})”,ids);但谢谢你,这很有效。我决定接受第三方的建议,因为它使团队的其他成员更容易调试项目。
var query = ((IQueryable)db.GetType().GetProperty(linkingTable).GetValue(db))
.Where($"@0.Contains({idField})", ids);