问题描述
我正在尝试传递包含需要过滤的字段的字符串列表。
string[] filterList = {"CostCenterId","Description",....}
对象定义:
public class CostCenter
{
public int Id { get; set; }
public string CostCenterId { get; set; }
public string Description { get; set; }
}
代替:
var filterData = data
.Where(x => x.CostCenterId.Contains(request.Filter) || x.Description.Contains(request.Filter));
是否可以通过传入Where()
来获取lambda表达式内的属性:string
?
是否可以做类似的事情:
var filterData = data
.Where(x => x["CostCenterId"].Contains(request.Filter) || x.["Desription"]
.Contains(request.Filter));
替换filterList中的值:
var filterData = data
.Where(x => x[filterList[0]].Contains(request.Filter) || x.[filterList[1]
.Contains(request.Filter));
我尝试了以下方法:
var filterData = data
.Where(x => x.GetType().GetField("CostCenterId").Name.Contains(filter) || x.GetType().GetField("Description").Name.Contains(filter));
但这不起作用
预期结果是过滤后的数据。我现在得到的结果为null,任何帮助将不胜感激
解决方法
EF使用IQueriable
接口,该接口接受expression trees,因此它可以分析您的代码并将其尝试转换为实际的SQL。这里的选项之一是自己为Where
子句构建过滤器表达式。对于仅处理字符串属性的有限情况,您可以执行以下操作(省略空白filterList
的边缘情况):
var filterValue = "test";// request.Filter
string[] filterList = { "CostCenterId","Description" };
var par = Expression.Parameter(typeof(CostCenter));
var stringContains = typeof(string).GetMethod(nameof(string.Contains),new[] {typeof(string)});
var predicate = filterList
.Select(f =>
{
var prop = Expression.Property(par,typeof(CostCenter),f);
return (Expression) Expression.Call(prop,stringContains,Expression.Constant(filterValue));
})
.Aggregate((agg,curr) => Expression.OrElse(agg,curr));
var filter = Expression.Lambda<Func<CostCenter,bool>>(predicate,par);
然后在查询中使用它:
var filterData = data.Where(filter);