【问题标题】:Getting Attribute Inside Linq "Where" using string使用字符串在 Linq“Where”中获取属性
【发布时间】:2020-10-18 07:31:47
【问题描述】:

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

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

是否可以通过传入 string 来获取 lambda 表达式中的属性:Where()

是否可以这样做:

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

但这不起作用,

预期结果是过滤后的数据。我现在得到的结果是空的,任何帮助将不胜感激

【问题讨论】:

  • “这不起作用”不多说了。这是一个 EF/其他 ORM 查询吗?您得到什么错误/意外结果?
  • 抱歉,我忘了在我的问题中提到这是一个 EF 查询。预期结果是过滤后的数据。我现在得到的结果是空的。
  • 使用 DynamicLinq,除非您这样做是为了在 EF 之上进行一些抽象,例如您正在尝试创建一个通用的 QueryTableWhere("tablename", "columnname1", "value1", "columnname2", "value2") 类型方法 - 在这种情况下,不要麻烦..它最终只会让你绊倒,让每一个角落的情况变得越来越难,而不是一开始就写一个直接的 LINQ 查询

标签: c# asp.net entity-framework linq lambda


【解决方案1】:

EF 使用接受expression treesIQueryable 接口,因此它可以分析您的代码并尝试将其转换为实际的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);

【讨论】:

  • 谢谢。我曾尝试实施此解决方案,但似乎收到以下错误:` 'IEnumerable' 不包含 'Where' 的定义和最佳扩展方法重载 'Queryable.Where(IQueryable, Expression>)' 需要一个类型为 'IQueryable' 的接收器
  • @ezennnn data 的类型是什么?
  • data 的类型是 IQueryable
  • 原来错误是因为,我已将 IQueryable 更改为 IEnumerable,将其更改为 IQueryable 类型解决了问题。谢谢
  • @ezennnn 如果答案对您有用,请将其标记为已接受(答案左侧的勾勒复选标记)=))
猜你喜欢
  • 1970-01-01
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
  • 1970-01-01
  • 2020-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多