2013-07-25 28 views
5

Trong MVC4, tôi đang cung cấp hộp Tìm kiếm cho người dùng để tìm kiếm bất kỳ giá trị nào trong Bảng. Vì vậy, tôi thực hiện Điều kiện Lọc Generic ở phía máy chủ trong C#Thực hiện Bộ lọc LINQ với Biểu thức

Cần giúp đỡ để kết hợp nhiều biểu thức để tạo thành biểu thức duy nhất

Expression<Func<T, bool>> 

Ví dụ

Bảng Cột

MenuText, Tên vai trò (Role.Name mapping), Actio nName

Bây giờ Nếu người dùng nhập vào hộp tìm kiếm cho ABC, có thể nằm trong bất kỳ hàng nào trong cột được hiển thị, cần phải lọc.

Mẫu

public class Menu 
{ 
    public string MenuText {get;set;} 
    public Role Role {get;set;} 
    public string ActionName {get;set;} 
} 

public class Role 
{ 
    public string Name {get;set;} 
} 

Cho đến nay tôi đã thực hiện

/// <summary> 
    /// string[] properties property.Name (MenuText, ActionName), including deeper Mapping names such as (Role.Name) 
    /// </summary> 
    public static Expression<Func<T, bool>> FilterKey<T>(string filterText, params string[] properties) 
    { 
     ParameterExpression parameter = Expression.Parameter(typeof (T)); 
     Expression[] propertyExpressions = properties.Select(
      x => !string.IsNullOrEmpty(x) ? GetDeepPropertyExpression(parameter, x) : null).ToArray(); 

     Expression<Func<T, bool>> predicate = PredicateBuilder.False<T>(); 
     foreach (Expression expression in propertyExpressions) 
     { 
      var toLower = Expression.Call(expression, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes)); 
      var like = Expression.Call(toLower, typeof(string).GetMethod("Contains"), Expression.Constant(filterText.ToLower())); 
      //TODO: Combine expressions to form single Expression<Func<T, bool>> expression 

     } 
     return predicate; 
    } 

     /// <summary> 
     /// To Get Deeper Properties such as Role.Name Expressions 
     /// </summary> 
     private static Expression GetDeepPropertyExpression(Expression initialInstance, string property) 
     { 
      Expression result = null; 
      foreach (string propertyName in property.Split('.')) 
      { 
       Expression instance = result ?? initialInstance; 
       result = Expression.Property(instance, propertyName); 
      } 
      return result; 
     } 
+0

Bạn đã đặt câu hỏi gần giống hệt nhau 3 lần trong 24 giờ qua ... – leppie

Trả lời

0

Cảm ơn cho NinjaNye, tôi đã mượn BuildOrExpression đã giải quyết được sự cố của tôi

Đây là giải pháp

public static Expression<Func<T, bool>> FilterKey<T>(string filterText, params string[] properties) 
     { 
      ParameterExpression parameter = Expression.Parameter(typeof (T)); 
      Expression[] propertyExpressions = properties.Select(
       x => !string.IsNullOrEmpty(x) ? GetDeepPropertyExpression(parameter, x) : null).ToArray(); 

      Expression like= propertyExpressions.Select(expression => Expression.Call(expression, typeof (string).GetMethod("ToLower", Type.EmptyTypes))).Select(toLower => Expression.Call(toLower, typeof (string).GetMethod("Contains"), Expression.Constant(filterText.ToLower()))).Aggregate<MethodCallExpression, Expression>(null, (current, ex) => BuildOrExpression(current, ex)); 
      return Expression.Lambda<Func<T, bool>>(like, parameter); 
     } 

     private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd) 
     { 
      if (existingExpression == null) 
      { 
       return expressionToAdd; 
      } 

      //Build 'OR' expression for each property 
      return Expression.OrElse(existingExpression, expressionToAdd); 
     } 


     private static Expression GetDeepPropertyExpression(Expression initialInstance, string property) 
     { 
      Expression result = null; 
      foreach (string propertyName in property.Split('.')) 
      { 
       Expression instance = result ?? initialInstance; 
       result = Expression.Property(instance, propertyName); 
      } 
      return result; 
     } 
6

Tôi đã tạo ra một vài phương pháp mở rộng tìm kiếm IQueryable rằng bạn sẽ có thể sử dụng

Full viết blog bài đăng ở đây:

http://jnye.co/Posts/6/c%23-generic-search-extension-method-for-iqueryable

dự án GitHub là ở đây (có một vài phần mở rộng thêm cho OR tìm kiếm:

https://github.com/ninjanye/SearchExtensions

public static class QueryableExtensions 
{ 
    public static IQueryable<T> Search<T>(this IQueryable<T> source, Expression<Func<T, string>> stringProperty, string searchTerm) 
    { 
     if (String.IsNullOrEmpty(searchTerm)) 
     { 
      return source; 
     } 

     // The below represents the following lamda: 
     // source.Where(x => x.[property] != null 
     //    && x.[property].Contains(searchTerm)) 

     //Create expression to represent x.[property] != null 
     var isNotNullExpression = Expression.NotEqual(stringProperty.Body, Expression.Constant(null)); 

     //Create expression to represent x.[property].Contains(searchTerm) 
     var searchTermExpression = Expression.Constant(searchTerm); 
     var checkContainsExpression = Expression.Call(stringProperty.Body, typeof(string).GetMethod("Contains"), searchTermExpression); 

     //Join not null and contains expressions 
     var notNullAndContainsExpression = Expression.AndAlso(isNotNullExpression, checkContainsExpression); 

     var methodCallExpression = Expression.Call(typeof(Queryable), 
                "Where", 
                new Type[] { source.ElementType }, 
                source.Expression, 
                Expression.Lambda<Func<T, bool>>(notNullAndContainsExpression, stringProperty.Parameters)); 

     return source.Provider.CreateQuery<T>(methodCallExpression); 
    } 
} 

này cho phép bạn viết một cái gì đó như:

string searchTerm = "test"; 
var results = context.Menu.Search(menu => menu.MenuText, searchTerm).ToList(); 

//OR for Role name 
string searchTerm = "test"; 
var results = context.Menu.Search(menu => menu.Role.Name, searchTerm).ToList(); 

Bạn cũng có thể tìm thấy followi ng bài viết hữu ích:

Tìm kiếm phương pháp mở rộng cho phép tìm kiếm accros nhiều thuộc tính:

http://jnye.co/Posts/7/generic-iqueryable-or-search-on-multiple-properties-using-expression-trees

Tìm kiếm phương pháp mở rộng cho phép nhiều hoặc thuật ngữ tìm kiếm trên một tài sản:

http://jnye.co/Posts/8/generic-iqueryable-or-search-for-multiple-search-terms-using-expression-trees

Các vấn đề liên quan