2011-02-06 58 views
1

我正在寫一些代碼,它需要LINQ to SQL IQueryable<T>並添加了進一步動態生成的Where子句。例如,下面是其中一種方法的骨架:可以意外評估LINQ to SQL IQueryable嗎?

IQueryable<T> ApplyContains(IQueryable<T> source, string field, string value) 
{ 
    Expression<Func<T, bool>> lambda; 
    ... dynamically generate lambda for p => p.<field>.Contains(value) ... 
    return source.Where(lambda); 
} 

我可能鏈幾種這些方法一起玩完帶有跳躍/送頁。

我正確地認爲,當最終評估IQueryable如果lambda表達式中有任何不能轉換爲SQL的異常將被拋出?特別是我擔心我可能會不小心做些事情,導致IQueryable提前評估,然後繼續評估內存(從而拉動成千上萬的記錄)。

從一些事情,我讀過,我懷疑IQueryable不會早這樣評價。任何人都可以確認這個嗎?

回答

3

是你在想,你的IQueryable可以在運行時拋出一個錯誤,如果表達式的一部分不能被轉化爲SQL正確。因此,我認爲在業務層類(如數據服務或存儲庫)中查詢是一個好主意,然後確保查詢由自動化測試覆蓋。

關於你的LINQ表達式在一個意想不到的時間來評估,基本原則要牢記的是,當你調用它的一個foreach你的表達式會。這還包括在後臺調用foreach的方法,如ToList()FirstOrDefault()

BTW一種簡單的方法判斷一個方法會調用一個foreach,迫使你的拉姆達評估是檢查對方法的返回值是否爲IQueryable。如果返回值是另一個IQueryable,那麼該方法可能只是添加到表達式中,但不會強制它進行評估。如果返回值是List<T>,匿名類型或任何看起來像數據而不是IQueryable的東西,那麼該方法必須強制您的表達式進行求值以獲取該數據。

+0

感謝您的提示。我確保將IQueryables保留在業務層中。作爲一個規則,我的實體框架上下文對象只有一個對業務層調用的生命週期 - 所以無論如何IQueryable無法評估超過該層。 – 2011-02-06 20:24:01

2

你的想法是正確的。

只要您在where子句中通過IQueryableExpression,就不會意外評估。

此外,對於開頭的擴展方法 「到」 將導致評價(即ToList(),ToArray的())。