如何将实体属性作为LINQ表达式的参数传递?

时间:2017-02-18 07:49:27

标签: c# linq lambda linq-to-entities expression

如何将实体属性作为LINQ表达式的参数传递?

public DropdownFilter(WhatTypeHere? ABC)
{
    // I want to store a selected property here
    // ABC must be a property of TEntity
    this.ABC = ABC;
}

// I want the class to encapsulate a LINQ query and just parametrize it with a property
public override IQueryable<TEntity> Filter(IQueryable<TEntity> filteredEntityCollection, string value)
{
    // ABC is a property of TEntity
    return filteredEntityCollection.Where(this.ABC == value);
}

我会像这样使用它:

new DropdownFilter<Invoice>(invoice => invoice.SomeProperty);

我已尝试使用Expression<Func<TEntity, string>>类参数,但它没有成功。它在抱怨

The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.

1 个答案:

答案 0 :(得分:1)

您必须手动构建LINQ表达式。首先,我会在您的类中添加第二个泛型参数,它将指定您要传递给过滤器的属性类型和值类型:

public class DropdownFilter<TEntity, TProperty>

接下来,您应该将属性选择器表达式传递给此过滤器类的构造函数:

private PropertyInfo propertyInfo;

public DropdownFilter(Expression<Func<TEntity, TProperty>> propertySelector)
{
    this.propertyInfo = (PropertyInfo)((MemberExpression)propertySelector.Body).Member;
}

最后,构建lambda表达式以按指定属性的给定值过滤可查询:

public IQueryable<TEntity> Filter(
   IQueryable<TEntity> filteredEntityCollection, TProperty value)
{
    var param = Expression.Parameter(typeof(TEntity), "p");

    var lambda = Expression.Lambda<Func<TEntity, bool>>(                
        Expression.Equal(
            Expression.Property(param, propertyInfo),
            Expression.Constant(value)
        ), param);

    return filteredEntityCollection.Where(lambda);
}

用法:

var filter = new DropdownFilter<Invoice, string>(i => i.ABC);
var result = filter(db.Invoices, "foo"); // strongly-typed parameter here

我会添加传递给构造函数的属性选择器表达式的验证。您应该检查它是否是MemberExpression。您可以验证属性类型以仅支持基本类型的属性。