C# 使用 Linq Expression 进行动态数据库过滤

Fil*_*sto 2 c# linq dynamic linq-to-sql

我尝试创建通用方法来过滤数据库中的不同实体,以避免为每个实体创建庞大的方法,并使用非常相似的 if 语句组合过滤规则。

现在我正在尝试创建表示相等比较的表达式,作为描述要比较的属性和某个值的参数表达式。

我的概念如何解决问题以及我根据其他帖子创建的内容显示了以下代码片段:

public class FuelCard 
{
    public int Id { get; set; }
    public string Number { get; set; }
    public virtual User User { get; set; }
}

public static IQueryable<TEntity> ApplyFilter<TEntity, TProperty>(
    this IQueryable<TEntity> query, 
    Expression<Func<TEntity, TProperty>> expr, TProperty value)
{
    Expression<Func<TEntity, bool>> predicate = param => true;

    var filterExpression = Expression.Equal(expr, Expression.Constant(value));
    var lambda = Expression.Lambda<Func<TEntity, bool>>(filterExpression);

    predicate = predicate.And(lambda);
    return query.Where(predicate);
}
Run Code Online (Sandbox Code Playgroud)

最后我想这样使用它:

IQueryable<FuelCard> query = // Get cards from database as IQueryable

query = query.ApplyFilter(x => x.Id, 85);
query = query.ApplyFilter(x => x.User.LastName + " " + x.User.FirstName, "Jon Green");
Run Code Online (Sandbox Code Playgroud)

我想定义匿名表达式来描述如何获取列的值,然后应用不同的过滤器(这里显示了使用 equal 方法的简单示例)。

但是当我调用 Expression.Equal 时,我收到错误,Func 和 Int32 没有二元运算符。

在所有示例中,都创建了具有属性名称的 Expression.Parameter 对象,但它们仅对实体类中的属性进行操作(不使用导航属性等)。 但是是否可以将过滤表达式与匿名属性表达式结合起来?

我希望我清楚地描述了我想要实现的目标以及与标准示例的区别,这是我的问题的根源

如果有人帮助我如何创建这样的过滤器,以便将参数中给定的表达式的结果与值进行比较,并将谓词应用于查询以便针对 sql 数据库运行它,我将非常感激:)

xan*_*tos 6

它是这样的:

public static IQueryable<TSource> WhereEqual<TSource, TProperty>(this IQueryable<TSource> query, Expression<Func<TSource, TProperty>> propertySelector, TProperty value)
{
    var body2 = Expression.Equal(propertySelector.Body, Expression.Constant(value));
    var lambda = Expression.Lambda<Func<TSource, bool>>(body2, propertySelector.Parameters);
    return query.Where(lambda);
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

IQueryable<FuelCard> query = // Get cards from database as IQueryable

query = query.WhereEqual(x => x.Id, 85);
query = query.WhereEqual(x => x.User.LastName + " " + x.User.FirstName, "Jon Green");
Run Code Online (Sandbox Code Playgroud)

一般来说,多个.Where()隐含在它们之间的&&(in) 中。因此,您只需根据属性选择器表达式加上 equals 加上传递的值创建一个表达式,然后返回.Where()使用该表达式的 a 。