2012-02-21 45 views
5

的Linq-to-SQL首先,我必須說我已經在StackOverflow上閱讀了幾篇文章,但是我無法得到期望的結果。結合兩個Expression <Func <T, bool>>(「where clause」)和/或

讓我解釋上下文(簡化):我使用Linq-to-SQL來查詢最近訪問商店的客戶和(可選)只獲得具有一定支付金額的客戶。假設我有一個包含客戶端,訪問和付款類的模型。

因此,着眼於Where表達,我想這樣的:

Expression<Func<Entityes.Clients, bool>> filter = null; 

filter = c => 
      c.Visits.Any(v => v.VisitDate > DateTime.Now.Date.AddMonths(-(int)visitsSince)); 


if (minPayment.HasValue && minPayment.Value > 0) 
{ 
    filter.And(
       c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 
} 

filter.And方法是一個擴展方法,在這個論壇上建議,下面你可以看到的定義:

public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, 
              Expression<Func<T, bool>> expression2) 
{ 
    InvocationExpression invokedExpression = 
     Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>()); 

    return Expression.Lambda<Func<T, bool>> 
     (Expression.And(expression1.Body, invokedExpression), expression1.Parameters); 
} 

但是,這並不適用於我的預期,並且結果不會按付款金額過濾。有數據或LINQ到SQL模型中沒有錯誤,因爲該代碼工作正常:

filter = c => 
      c.Visits.Any(v => v.VisitDate > DateTime.Now.Date.AddMonths(-(int)visitsSince))) 
      && c => c.Payments.Sum(p => p.Quantity) > minPayment.Value; 

不過,我不希望因爲我有一些更復雜的場景中,我需要使用的最後一個代碼使用每個部分的「和/或」組合逐步構建過濾器表達式。 PD:我是一個「ADO.Net DataSets」傢伙,試圖學習Linq-to-SQL和即將推出的Entity Framework,我希望能很快對StackOverflow社區有所幫助。

+3

p.s.,您應該使用'Expression.AndAlso()'方法來生成邏輯AND表達式('&&')。 'Expression.And()'產生按位AND表達式('&')。 – 2012-02-21 22:01:31

回答

3

您不會將And的結果分配給任何東西。

我想你的代碼的相應部分應改爲如下:

if (minPayment.HasValue && minPayment.Value > 0) 
{ 
    filter = filter.And(
      c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 
} 

的事情是,你(或SO是如你所提到的)And功能返回含有兩種表達的共同表達。它不會改變它被調用的對象。

+0

哎喲...謝謝! – 2012-02-21 21:54:28

+0

@FranCD不客氣。順便說一句,我冒昧地將您的問題回滾到原始版本,以便更多訪問者看到實際的原始代碼。否則,下面的答案是沒有意義的。 – Krizz 2012-02-21 21:59:50

0

退房LinqKit和它的PredicateBuilder類:http://www.albahari.com/nutshell/predicatebuilder.aspx

+0

我使用的實現來自PredicateBuilder類,並且不起作用...錯誤在哪裏? – 2012-02-21 21:43:21

+0

@FranCD你的使用有誤,請參閱我的答案。 – Krizz 2012-02-21 21:44:13

1

的問題是這一行:

filter.And(c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 

And方法返回一個你沒有分配到任何其他委託。嘗試:

filter = filter.And(c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 

只是爲了澄清,And是取兩個表達式,並結合了它們的邏輯來創建新的表達的方法。它不會更改它在其上執行的表達式,但會將新表達式作爲返回值返回。所以在你的代碼中,你調用了filter.And(...),但是沒有對返回值做任何事情,所以filter仍然引用了原始的lambda表達式。

相關問題