2009-01-04 44 views
8

Tôi cố gắng để viết một hàm tĩnh để Hoặc hai biểu thức, nhưng nhận được lỗi sau:Expression.Or, Tham số 'mục' không nằm trong phạm vi

The parameter 'item' is not in scope.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: The parameter 'item' is not in scope.

phương pháp:

public static Expression<Func<T, bool>> OrExpressions(Expression<Func<T, bool>> left, Expression<Func<T, bool>> right) 
{ 
    // Define the parameter to use 
    var param = Expression.Parameter(typeof(T), "item"); 

    var filterExpression = Expression.Lambda<Func<T, bool>> 
     (Expression.Or(
      left.Body, 
      right.Body 
     ), param); 
    // Build the expression and return it 
    return (filterExpression); 
} 

chỉnh sửa: thêm thông tin

Biểu thức đang được gửi đến từ phương thức bên dưới, thực thi tốt. nếu có một cách tốt hơn hoặc kết quả tôi là tất cả tai. Ngoài ra, tôi không biết có bao nhiêu người đang được hoặc muốn trước.

public static Expression<Func<T, bool>> FilterExpression(string filterBy, object Value, FilterBinaryExpression binaryExpression) 
{ 
    // Define the parameter to use 
    var param = Expression.Parameter(typeof(T), "item"); 

    // Filter expression on the value 
    switch (binaryExpression) 
    { 
     case FilterBinaryExpression.Equal: 
      { 
       // Build an expression for "Is the parameter equal to the value" by employing reflection 
       var filterExpression = Expression.Lambda<Func<T, bool>> 
        (Expression.Equal(
         Expression.Convert(Expression.Property(param, filterBy), typeof(TVal)), 
         Expression.Constant(Value) 
        ), 
        param); 
       // Build the expression and return it 
       return (filterExpression); 
      } 

chỉnh sửa: thêm thông tin thậm chí nhiều hơn

Ngoài ra, là có một cách tốt hơn để làm một hay? Hiện tại .Where (ràng buộc) hoạt động tốt ở nơi có ràng buộc là loại biểu thức>. Làm thế nào tôi có thể làm ở đâu (constraint1 hoặc constraint2) (với ràng buộc n'th)

Cảm ơn bạn trước!

Trả lời

9

Vấn đề là Biểu thức bạn đang tạo trong phương thức OrExpressions sẽ tái sử dụng phần thân của hai biểu thức. Các cơ quan đó sẽ chứa các tham chiếu đến ParameterExpression của chúng đã được định nghĩa trong FilterExpression.

Sửa chữa sẽ là viết lại các phần bên trái và bên phải để sử dụng ParameterExpression mới. Hoặc để vượt qua ParameterExpression gốc cùng. Không phải vì hai ParameterExpression có cùng tên mà chúng đại diện cho cùng một tham số.

+0

Cảm ơn bạn! Hãy thử và vượt qua cùng một tham số ngay bây giờ – ccook

+0

Bạn của tôi, thật tuyệt vời :) – ccook

2

Tôi không chắc chắn về các điều khoản thích hợp ở đây, nhưng về cơ bản các tham số biểu thức không tương đương ngay cả khi chúng có cùng tên.

Điều đó có nghĩa rằng

var param1 = Expression.Parameter(typeof(T), "item"); 
var param2 = Expression.Parameter(typeof(T), "item"); 

param1 != param2 

param1 và param2 sẽ không phải là điều tương tự nếu sử dụng trong một biểu thức.

Cách tốt nhất để giải quyết vấn đề này là tạo một tham số lên phía trước cho biểu thức của bạn, sau đó chuyển nó tới tất cả các hàm trợ giúp cần tham số.

CHỈNH SỬA: Ngoài ra, nếu bạn đang cố gắng tự động soạn các mệnh đề trong LINQ, bạn có thể dùng thử PredicateBuilder.

+0

Cảm ơn bạn :) Tôi đã làm lại phương pháp để truyền vào cùng một tham số cho phương thức của trình trợ giúp và tất cả đều tốt. Tôi nhìn vào PredicateBuilder để hy vọng làm sạch mọi thứ lên – ccook

+0

Xem ra, vì PredicateBuilder từ Ben & Joe Albahari không làm việc cho Entity Framework. Xem câu trả lời của tôi cho một phiên bản cố định. –

4

Như đã gợi ý, here bạn có thể tìm thấy rất thoải mái (làm việc) mã này

public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) 
{ 
    var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 
    return Expression.Lambda<Func<T, bool>>(Expression.Or(expr1.Body, invokedExpr), expr1.Parameters); 
} 

mà bạn có thể thích ứng với nhu cầu của bạn và đó là không bị ràng buộc (IMHO) để LINQ.

+0

Đẹp và sạch, ty – ccook

+0

Xem ra, vì mã này không hoạt động cho Entity Framework. Xem câu trả lời của tôi cho một phiên bản cố định. –

1

Giải pháp của Fabrizio cũng xảy ra với tôi nhưng vì tôi đã cố gắng kết hợp hai biểu thức sẽ được thực thi dưới dạng truy vấn sqq 2 sql, tôi nghĩ nó sẽ thực thi trong bộ nhớ chứ không phải máy chủ sql.

Tôi đã được viết - Linq-To-Sql nhận ra rằng lời gọi là biểu thức lambda và do đó vẫn tạo ra tối ưu hóa sql.

2

Đối với những người, người tìm thấy trang này bằng công cụ tìm kiếm và sẽ sử dụng các PredicateBuilder từ Bến & Joe Albahari, xem ra, vì nó không làm việc với Entity Framework.

Thay vào đó hãy thử this fixed version.

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