【问题标题】:How to construct Where Expression dynamically in Entity Framework?如何在实体框架中动态构造 Where 表达式?
【发布时间】:2016-08-27 15:42:52
【问题描述】:

我查看了this answer,了解如何在实体框架中动态创建 OrderBy 表达式。但我还想构建一个动态的 Where 表达式。类似这样的东西:

public IEnumerable<InventoryItem> GetAll(string filterBy, object value)
{
  var results = new List<InventoryItem>();
  using (var db = new InventoryDb())
  {
    if (QueryHelper.PropertyExists<InventoryItem>(filterBy)) 
    {
      var query = db.rri_InventoryItems.WhereByProperty(filterBy, value); 

      foreach(var item in query.Where(expr))
      {
        results.Add(ConvertItem(item));
      }   
    }            
  }
  return results;
}

传入要过滤的属性和一个值作为 ab 对象。 Queryable 有两种方法 Where 都采用两个参数,所以我什至不确定哪个是正确的。

在这一点上,我更加迷失了。我不确定如何重构原始 OrderByProerty 方法以提供 WhereByProperty。我知道我在这里所拥有的是完全错误的。我不知道该怎么处理它。

理想情况下,我希望通过提供一组对象来进一步扩展这一点,这些对象集合可用于使用 andsor 运算符构建查询。 p>

【问题讨论】:

    标签: entity-framework linq where-clause expression-trees


    【解决方案1】:

    Queryable 有两种 Where 方法,它们都带有两个参数,所以我什至不确定哪个是正确的。

    您需要接收Expression&lt;Func&lt;T, bool&gt;&gt; predicate 的那个。

    以下是动态构建类似于(T item) =&gt; item.Property == value 的谓词的方法:

    public static partial class QueryableExtensions
    {
        public static IQueryable<T> WhereEquals<T>(this IQueryable<T> source, string member, object value)
        {
            var item = Expression.Parameter(typeof(T), "item");
            var memberValue = member.Split('.').Aggregate((Expression)item, Expression.PropertyOrField);
            var memberType = memberValue.Type;
            if (value != null && value.GetType() != memberType)
                value = Convert.ChangeType(value, memberType);
            var condition = Expression.Equal(memberValue, Expression.Constant(value, memberType));
            var predicate = Expression.Lambda<Func<T, bool>>(condition, item);
            return source.Where(predicate);
        }
    }
    

    我尝试以这样的方式编写它,以便您可以单步执行代码以了解它的作用。唯一可能需要解释的行是:

    var memberValue = member.Split('.').Aggregate((Expression)item, Expression.PropertyOrField);
    

    这是一种处理嵌套属性的简单方法,例如 obj.Prop1.Prop2 等。如果您不需要这样的功能,您可以简单地使用它来代替:

    var memberValue = Expression.PropertyOrField(item, member);
    

    【讨论】:

      【解决方案2】:

      我还不需要嵌套属性。我稍微修改了您的代码并使其正常工作:

          public static IQueryable<T> WhereEquals<T>(
             this IQueryable<T> source, string propertyName, object value)
          {
              if (typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase |
                  BindingFlags.Public | BindingFlags.Instance) == null)
              {
                  return null;
              }
      
              ParameterExpression parameter = Expression.Parameter(typeof(T), "item");
              Expression whereProperty = Expression.Property(parameter, propertyName);
              Expression constant = Expression.Constant(value);
              Expression condition = Expression.Equal(whereProperty, constant);
              Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(condition,parameter);
              return source.Where(lambda);
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-22
        • 1970-01-01
        • 2010-10-06
        • 1970-01-01
        • 1970-01-01
        • 2011-05-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多