2010-06-15 18 views
5

Chúng tôi có một dự án sử dụng LINQ to SQL, mà tôi cần viết lại một vài trang tìm kiếm để cho phép khách hàng chọn xem họ có muốn thực hiện hay không hoặc tìm kiếm.LINQ PredicateBuilder với bộ lọc AND, OR và NOT có điều kiện

Tôi mặc dù về việc làm lại các truy vấn LINQ bằng cách sử dụng PredicateBuilder và đã làm việc này khá tốt, tôi nghĩ vậy. Tôi có hiệu quả có một lớp có chứa các vị từ của tôi, ví dụ:

internal static Expression<Func<Job, bool>> Description(string term) 
{ 
    return p => p.Description.Contains(term); 
} 

Để thực hiện tìm kiếm tôi đang làm điều này (một số mã bỏ qua cho ngắn gọn):

public Expression<Func<Job, bool>> ToLinqExpression() 
{ 
    var predicates = new List<Expression<Func<Job, bool>>>(); 
    // build up predicates here 

    if (SearchType == SearchType.And) 
    { 
     query = PredicateBuilder.True<Job>(); 
    } 
    else 
    { 
     query = PredicateBuilder.False<Job>(); 
    } 

    foreach (var predicate in predicates) 
    { 
     if (SearchType == SearchType.And) 
     { 
      query = query.And(predicate); 
     } 
     else 
     { 
      query = query.Or(predicate); 
     } 
    } 
    return query; 
} 

Trong khi tôi là hợp lý hạnh phúc với điều này , Tôi có hai mối quan tâm:

  1. Các khối if/else đánh giá thuộc tính SearchType giống như chúng có thể là mùi mã tiềm năng.
  2. Khách hàng hiện đang nhấn mạnh vào việc có thể thực hiện 'và không phải'/'hoặc không' tìm kiếm.

Để giải quyết điểm 2, tôi nghĩ rằng tôi có thể làm điều này bằng cách đơn giản viết lại biểu thức của tôi, ví dụ:

internal static Expression<Func<Job, bool>> Description(string term, bool invert) 
{ 
    if (invert) 
    { 
     return p => !p.Description.Contains(term); 
    } 
    else 
    { 
     return p => p.Description.Contains(term); 
    } 
} 

Tuy nhiên điều này cảm thấy giống như một chút của một kludge, mà thường có nghĩa là có một giải pháp tốt hơn ra đó. Bất cứ ai có thể khuyên bạn nên làm thế nào điều này có thể được cải thiện? Tôi biết về LINQ động, nhưng tôi thực sự không muốn đánh mất khả năng gõ mạnh mẽ của LINQ.

Trả lời

8

Nếu bạn đang tìm kiếm dòng ít bạn có thể thay thế if/else với nhà điều hành ternary:

query = SearchType == SearchType.And ? PredicateBuilder.True<Job>() : PredicateBuilder.False<Job>(); 

    foreach (var predicate in predicates) 
    { 
     query = SearchType == SearchType.And ? query.And(predicate) : query.Or(predicate); 
    } 

cho 'and not'/'or not' phần các nhà điều hành ! nên làm các trick.

PD: Bạn có kiểm tra phần foreach được thiết lập một cách chính xác các vị ?, as far as i nhớ bạn đang xây dựng các biểu thức sẽ được thực hiện vào thời điểm sau này trong thời gian, vì vậy bạn có thể có một tài liệu tham khảo theo nghĩa đen chỉ để tập hợp biến vị ngữ cuối cùng trong lần lặp cuối cùng, và đó là lý do tại sao bạn phải sử dụng biến tạm thời để lưu giá trị của mỗi lần lặp.

EDIT: Nếu bạn muốn phủ nhận một chương trình ngôn luận, đó là một khó khăn, bạn có thể thử một cái gì đó như:

internal static Expression<Func<Job, bool>> Description(string term, bool invert) 
     { 
      return NegateExp<Func<Job, bool>>(p => p.Description.Contains(term), invert); 
     } 

Và phương pháp NegateExp sẽ được giống như:

public static Expression<TDelegate> NegateExp<TDelegate>(Expression<TDelegate> expression, bool inverse) 
     { 
      if (inverse) 
      { 
       return Expression.Lambda<TDelegate>(Expression.Not(expression.Body), expression.Parameters); 
      } 
      return expression; 
     } 

Bạn có thể xem câu hỏi này để biết thêm ví dụ Is there any way to negate a Predicate?

+0

Tôi đã định hình được gen SQL được dựng lên và tất cả đều ổn. Nhận xét công bằng về việc sử dụng toán tử bậc ba mặc dù tôi quan tâm nhiều hơn đến sự trùng lặp trong các biến vị ngữ được cập nhật của tôi. – richeym

+0

sử dụng Expression.Not với đại biểu phải hữu ích ở đây. Đã thêm một ví dụ nhỏ ở trên. – JOBG

+0

Đó là một thú vị, sẽ cho nó một thử vào ngày mai.Nó cũng xảy ra với tôi rằng tôi có thể chỉ đơn giản là XOR biểu thức với tham số nghịch đảo - Nó hoạt động nhưng nó tạo ra một số SQL khá kém hiệu quả. – richeym

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