2011-12-22 67 views
2

我需要構建一個查詢來提供分頁結果。部分過濾發生在數據庫中,部分過濾發生在內存中的對象中。在linq中混合數據庫和對象查詢並提供分頁結果

下面是一個簡單的示例,顯示了我可以做什麼,即對數據庫運行linq查詢,然後使用自定義代碼對其進行進一步過濾,然後使用skip/take進行分頁,但這樣會非常低效,因爲它需要加載與我的查詢的第一部分匹配的所有項目。

Things.Where(e=>e.field1==1 && e.field2>1).ToList() 
      .Where(e=>Helper.MyFilter(e,param1,param2)).Skip(m*pageSize).Take(pageSize); 

MyFilter函數使用不位於在數據庫中,它是與其他參數(paramX在上面的例子)

運行的附加數據是否有來處理這種情況,而無需加載初始的優選方式完全在記憶中。

回答

1

是的,查詢和頁面在數據庫級別。無論Helper.MyFilter中的邏輯是否需要在sql查詢中。

另一個選項,這是更侵入你的代碼庫。是保存視圖模型,以及實體更改時的域實體。部分視圖模型將包含Helper.MyFilter(e)的結果,因此您可以快速高效地查詢它。

+0

您的第一個選項是不可能的,因爲MyFilter函數使用了一些不在數據庫中的附加信息。保存MyFilter的結果不可行,因爲Myfilter實際上有其他參數。我已經更新了相應的問題。 – cellik

+0

如果您將MyFilter的結果保存在數據庫中,那麼它的計算方式並不重要,只是它是如此。但在實體更改時保存它,而不是在查詢數據庫時保存。 –

+1

如果您在數據庫之外有需求,則無法在數據庫中分頁結果,因此必須在分頁之前將結果加載到內存中。 –

0
.ToList() 

您正在將您的查詢轉換爲內存對象,即列表,從而導致查詢執行,然後您提供數據分頁。

你可以把它們都放在一個Where條款:

Things.Where(e=>e.field1==1 && e.field2>1 
      && e=>Helper.MyFilter(e)).Skip(m*pageSize).Take(pageSize); 

,然後.ToList()。 這樣你就可以讓Linq給Sql一個生成查詢的機會,讓你只獲得你想要的數據。

或者您爲什麼要這麼做有一個特別的原因 - 轉換爲內存對象,然後過濾?雖然我沒有看到這一點。在對數據庫實際執行之前,您應該能夠過濾掉Linq to Sql查詢中不需要的結果。

編輯

,我可以從討論中看到,你有幾種選擇。

如果您有大量的數據並且執行的讀取次數多於寫入次數,那麼在可能的情況下將結果從Helper.MyFilter保存到數據庫中可能是明智的。這樣,您可以提高選擇性能,因爲您不會從數據庫中提取所有數據,並且您還可以在SELECT本身上獲得更多的過濾數據。

或者你可以採取另一種方法。您可以將Helper課程放在單獨的程序集中,並且可以使用reference that assembly from SQL Server。這將使您能夠將分頁邏輯放入數據庫並使用您的代碼。

+0

這裏假設'Helper.MyFitler(e)'中的邏輯可以轉換爲sql。 –

+0

正如Jason提到的,這個函數不能正常工作,因爲函數包含無法轉換爲SQL的代碼。這就是爲什麼我使用ToList – cellik

+0

@cellik - 你必須按照正確的順序做所有事情嗎?我在想,也許你可以通過重排序來「部分優化」查詢:.Where(e => e.field1 == 1 && e.field2> 1).Skip(m * pageSize).Take(pageSize).Where e => Helper.MyFilter(e)) – TheBoyan