2017-09-14 53 views
0

如何根據應在where子句中使用or操作的一組過濾器或表達式過濾數據?使用OR操作加入多個複雜子句的過濾數據where函數

例如,有一類:

class DTOFilter 
{ 
    public string Domain { get; set; } 
    public string Mobile { get; set; } 
} 

,要求基於過濾器的列表旁邊的方式來過濾Users列表:

u=> 
(u.Email.Contains(filters[0].Domain) && u.PhoneNumber.StartsWith(filters[0].Mobile)) || 
(u.Email.Contains(filters[1].Domain) && u.PhoneNumber.StartsWith(filters[1].Mobile)) || 
... 

顯然應該在automaticaly被建表格如:

db.Users.Where(filters.Filter<Users, DTOFilter>(
         (u, f) => u.Email.Contains(f.Domain) 
           && u.PhoneNumber.StartsWith(f.Mobile)) 
       .Or()) 

回答

1

要執行該任務,需要執行兩個功能:

  1. Or表達加入功能
  2. 篩選數據分割功能

或功能經過表達式的集合,加入他們的Or表達類似(((expression1 or expression2) or expression3) or expression4)

public static Expression<Func<T, bool>> Or<T>(
    this IEnumerable<Expression<Func<T, bool>>> source) 
    { 
     var expressions = source.ToList(); 
     if (expressions.Count == 0) 
      return x => false; 

     var orExpression = expressions 
      .Select(e => e.Body) 
      .Aggregate((a, b) => Expression.OrElse(a, b)); 
     var parameter = expressions.First().Parameters.First(); 
     return Expression.Lambda<Func<T, bool>>(orExpression, parameter); 
    } 

這函數已經可以使用,如果過濾器已經是有效的表達式。

過濾拆分數據函數,應該乘以選擇器表達式,並將結果表達式參數替換爲確切的對象值。過濾數據羣在函數中完成:

public static IEnumerable<Expression<Func<T, bool>>> Filter<T, TData>(
    this IEnumerable<TData> data, 
    Expression<Func<T,TData, bool>> selector) 
{ 
    var parameter = selector.Parameters.First(p => p.Type.IsAssignableFrom(typeof(T))); 

    return data.Select(item => Expression.Lambda<Func<T, bool>>(
     new DataVisitor<TData>(item).Visit(selector.Body), parameter)); 
} 

下一頁遊客實施有助於精確值替換參數:

public class DataVisitor<T> : ExpressionVisitor 
{ 
    private readonly ConstantExpression _data; 

    public DataVisitor(T dataItem) 
    { 
     _data = Expression.Constant(dataItem); 
    } 

    protected override Expression VisitParameter(ParameterExpression node) 
    { 
      return node.Type.IsAssignableFrom(typeof(T)) 
        ? _data : base.VisitParameter(node); 
    } 
} 

構建表達是正確的lambda表達式可以由EF解析表達式樹解析器。