0

我有一個OrderLines的集合。每個OrderLine都有一個多對一的產品。對於所有訂單,我都有一個搜索窗口 - 默認情況下 - 顯示網格中的所有訂單。使用這個相同的窗口,我可以過濾包含給定產品的所有訂單。我們的客戶每天產生約700份訂單,​​訂單平均約有35行。NHibernate:在詳細信息具有多對一關係的主細節中解決N + 1問題?

在searchwindow中,我只顯示存儲在Order對象本身中的信息。但是,如果我篩選特定的產品,它將初始化我的延遲加載關係到OrderLine集合以及我的OrderLine中的我的產品的多對一關係。每條訂單行都是逐行查詢,並且每行都有一個對產品表的單獨查詢。

所以我平均每次訂購35個查詢以初始化所有訂單行,再加上35個查詢以獲取與該訂單行相關聯的產品。

一次加載所有訂單行及其關聯產品的最佳方式是什麼(並且如果不可能,則每個訂單的訂單行都不可能)?我知道我可以將我的多對一映射到訂單行中的產品,作爲fetch =「join」,但這仍然會使我得到35個單一查詢來獲得訂單行+產品。

供參考:目前我加載一切懶惰。

有什麼建議嗎?我可以在這裏使用Future嗎?

問候,泰德

回答

0

在這種情況下,我不會檢索命令實體本身。 我會創建一個'View'類,通過使用NHibernate Projects,我會返回那些僅包含您感興趣的信息的'View'類,並將其放入概覽窗體或頁面中。 當搜索時,您可以執行一個新的查詢(只有一個),它將檢索您感興趣的'OrderView'實例。

當您想要編輯訂單或查看其詳細信息時,我會加載實體。

+0

我不能延遲訂單的加載,因爲我需要對產品進行過濾,所以我必須獲取所有生產線,併爲每一行生產產品,然後我可以過濾ProductCode屬性。我可能會錯過你的觀點:) – TedOnTheNet 2012-04-27 08:40:11

+1

當搜索/過濾時,我會使用NHibernate重新查詢數據庫,並且使用投影並不是所有產品都需要檢索。 – 2012-04-27 16:56:24

3

你的batch-size設置爲?

留下你懶加載的是和兩個集合映射將其設置爲35,這應該減少1 + 35 + 35的查詢1 + 1 + 1

<bag ... batch-size='35' ..> 

另外,作爲由斯特凡你指出還需要在課程上設置batch-size='35'

+0

與提案一致,但計算結果不正確。它會將1 + 35 + 35減少到1 + 1 + 1,但前提是您還要在產品類別上指定批量。 – 2012-04-27 09:24:47

+0

啊,是的,很好,謝謝Stefan,這是因爲他要多對一的權利? – Rippo 2012-04-27 09:33:43

+0

是的,在使用多對一時,您需要在類上指定批量大小。 – 2012-04-27 12:24:22

0

您是否在內存中對加載的實體執行過濾操作?通常,您只想執行包含相關產品訂單行的訂單的查詢。那麼你只需要根據查詢結果來填充你的窗口。不需要遍歷所有訂單和所有訂單行,只用一小部分數據填充窗口。

在數據庫服務器上過濾通常要比從服務器獲取所有數據並在C#中執行過濾要快得多。

您的描述不完全清楚:鑑於您已經過濾了要顯示的訂單,您是否需要訪問訂單行和產品?
- 如果沒有,您可以使用上述解決方案。
- 如果是,您可以對已過濾的訂單查詢執行聯合提取,以將訂單行直接與訂單一起加載。加入抓取不僅可以用於<多對一>,還可以用於<一對多>,因此您可以一次將一些根實體與其子代一起加載。如果根實體具有許多列和多個子元素,則會存在一些缺點,因爲查詢冗餘地爲每個子元素檢索根實體的數據。然而,在許多情況下(取決於整個系統配置),加入抓取的好處大大超過成本。

在查詢數據並且事先並不清楚下列代碼實際需要哪些數據的情況下,使用批量選擇(使用批量大小>)可以大大減少數據庫往返次數。