如何将表达式树与带有null选项的对象一起应用

时间:2019-03-29 14:31:05

标签: c# entity-framework linq expression

我有这个对象

public class Ledger
{
   public string fund {get;set;}
   public string location {get;set;}
   public string costCenter {get;set;}
   public string objects {get;set;}
}

我正在使用此过滤器选项,这意味着每个值都可以为null或可以填充。在SQL中,查询看起来像是

SELECT FROM GlAccts WHERE fund = "10" AND location = "1" AND objects = "45"
SELECT FROM GlAccts WHERE objects = "45"
SELECT FROM GlAccts WHERE location = "1" AND objects = "45"

我正在尝试将其转换为linq,我遇到了一个表达式树,听起来不错,但确实有一些问题,

  1. 如何返回带有表达式树的GlAccts列表
  2. 当我的表达式为null时,如何将表达式与AND合并。

这是我目前拥有的。

// filtersObject, is my object which would contains fund,location,costCenter,object, just to note it is currently in a foreach (var filtersObjects) since I plan to have multiple filter objects but i am not worry about this section.
// my active list right now is List<glUserAccess> but I dont know where to apply this


            ParameterExpression pe = Expression.Parameter(typeof(GlAccts), "glAccts");

            Expression e1 = null;
            Expression e2 = null;
            Expression e3 = null;
            Expression e4 = null;

            // Fund EQ ""
            if (!string.IsNullOrEmpty(filtersObject.fund)) {
                Expression left = Expression.Property(pe, typeof(string).GetProperty("fund")); ;
                Expression right = Expression.Constant(filtersObject.fund, typeof(string));
                e1 = Expression.Equal(left, right);
            }

            // Location EQ ""
            if (!string.IsNullOrEmpty(filtersObject.location)) {
                Expression left = Expression.Property(pe, typeof(string).GetProperty("location")); ;
                Expression right = Expression.Constant(filtersObject.location, typeof(string));
                e2 = Expression.Equal(left, right);
            }

            // Cost Center EQ ""
            if (!string.IsNullOrEmpty(filtersObject.costCenter)) {
                Expression left = Expression.Property(pe, typeof(string).GetProperty("costCenter")); ;
                Expression right = Expression.Constant(filtersObject.costCenter, typeof(string));
                e3 = Expression.Equal(left, right);
            }

            // Objects EQ ""
            if (!string.IsNullOrEmpty(filtersObject.objects)) {
                Expression left = Expression.Property(pe, typeof(string).GetProperty("objects")); ;
                Expression right = Expression.Constant(filtersObject.objects, typeof(string));
                e4 = Expression.Equal(left, right);
            }

            var e1e2 = Expression.AndAlso(e1,e2);
            var e1e2e3 = Expression.AndAlso(e1e2, e3);
            var e1e2e3e4 = Expression.AndAlso(e1e2e3, e4);

            var ExpressionTree = Expression.Lambda<Func<GlAccts, bool>>(e1e2e3e4, new[] { pe });

1 个答案:

答案 0 :(得分:1)

您可以将子表达式与AndAlso组合在一起。接下来的代码使用反射从Ledger获取所有属性并创建动态lambda表达式:

public static Expression<Func<T, bool>> CreateExpression<T>(Ledger ledger)
{
    var parameter = Expression.Parameter(typeof(T), "x");

    Expression body = null;
    foreach (var property in ledger.GetType().GetProperties())
    {
        var value = property.GetValue(ledger);
        if (value == null)
            continue;

        var equals = Expression.Equal(
            Expression.Property(parameter, property.Name),
            Expression.Constant(value));

        body = body == null ? equals : Expression.AndAlso(body, equals);
    }

    if (body == null) // no filters
        body = Expression.Constant(true);

    var lambda = Expression.Lambda<Func<T, bool>>(body, parameter);
    return lambda;
}

如果Ledger中的所有属性都为null,则它将返回x => true,该lambda将不会过滤任何内容