2014-04-23 90 views
1

當試圖在ravendbRavenDB - DateTime.Subtract查詢異常

RavenSession.Query<R>().Any(x => DateTime.Now.Subtract(x.Submitted).TotalSeconds < 61) 

執行以下查詢參數異常(「無法明白表達」)被拋出。

當凡IsSpam被定義爲這個碼被重寫爲

RavenSession.Query<R>().Any(IsSpam()) 

protected Func<R, bool> IsSpam() 
    { 
     return r => DateTime.Now.Subtract(r.Submitted).TotalSeconds < 61; 
    } 

的代碼執行順利。 這兩個查詢之間的執行有什麼區別?

回答

0

你不能在RavenDB中做這樣的查詢。 IsSpam方法可能正在做一些您並不期待的事情。 您的查詢存在的問題是您需要我們執行計算來回答它。這意味着我們無法將查詢優化爲索引查找。我們不允許這樣的查詢。

相反,使用此查詢:

var cutoff = DateTime.Now + TimeSpan.FromSeconds(61); 

RavenSession.Query<R>.Where(x=>x.Submitted > cutoff).ToList(); 
+0

謝謝您的回答。儘管它沒有回答原來的問題(爲什麼將lambda創建爲相同的語句?)我會接受它。 – Levon

0

表達式樹解析變得非常複雜,我並不十分確定發生了什麼,儘管我不確定您的發佈代碼是否與IsSpam()實現完全相同,但我不太確定現在寫入r參數如何進入。

它可能與第一個示例中創建的閉包以及外部值如何泄漏到其中,而第二個示例Func更明確,不允許發生這些瘋狂的關閉事件。

無論如何,Raven的LINQ提供者的要點是要提供表達式樹並將其發送到服務器,並讓服務器能夠將其轉換爲Lucene查詢語法。像所有的抽象概念一樣,它會泄漏,所以並非一切皆有可能,但通常簡單的事情將比複雜或迂迴的事情更好地發揮作用。

而不是使用日期時間的減​​方法,它可能工作最好使用標準的運營商:

RavenSession.Query<R>().Any(x => (DateTime.Now - x.Submitted).TotalSeconds < 61) 

由創建表達式樹將大大不同(可能更容易解析)比你的第一個,我會期待的。

此外,我必須補充,在您的查詢中小心使用DateTime.Now。每次運行查詢時,值顯然都會有所不同,所以您將永遠無法利用Raven客戶端緩存結果的能力。