使用字符串在Linq“哪里”内部获取属性实体框架

问题描述

我正在尝试传递包含需要过滤的字段的字符串列表。

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);