2010-09-23 23 views
2

考慮:

  • 您有層表示,業務和數據的架構。
  • 您正在應用領域驅動設計。
  • 您正在使用一種對象關係映射器,它允許您創建面向對象的查詢(例如,可讓您創建HQL查詢的NHibernate)。

問:

向一個層,你應該把面向對象的查詢?何處將分層體系結構中的面向對象的查詢?

我的想法:

我想將它們放入表示層通常是沒有意義的。但我不知道是否將它們放入業務或數據層。

例(NHibernate的):

說你的業務邏輯需要一些方法GetCustomersPossiblyInterestedIn(產品P)。然後,您可以創建一個複雜的HQL查詢來選擇客戶對象,其中客戶已經購買了與p相同類別的產品。

變元)

,一方面,我會說這查詢顯然是業務邏輯,因爲客戶是基於她是否買一個產品一個產品可能感興趣的處理決定同一類別是一個商業決策。您也可以選擇以相似價格購買同一類別中的多個產品的客戶,例如

參數b)中

在另一方面,業務層不應當取決於數據層,所以直接使用NHibernate在業務層環的警鈴。

可能的解決方法1)

創建您在業務層數據層使用,並轉換爲HQL自己的面向對象的查詢語言。 我認爲這會造成很多開銷。如果您使用基於查詢對象而不是解析查詢語言的查詢語言,那麼您可能會付出一些努力,但我的反對意見仍然適用。

可能的解決方法2)

在業務層直接使用NHibernate是O.K.,因爲抽象級別NHibernate的是能夠與HQL,ISession的等提供適合的業務層。沒有必要包裝它。

你覺得呢?

編輯:

爲密切相關的討論參見"Repository is the new Singleton""The false myth of encapsulating data access in the DAL"由Ayende Rahien。

+0

您是否將規範模式視爲解決方案3? – Paco 2010-09-23 15:24:38

+0

到目前爲止,沒有。但是,謝謝,我會看看它。 – 2010-09-26 20:13:44

回答

0

我更喜歡使用某種存儲庫來包裝NHibernate(或其他ORM)。例如。在NHibernate的情況下,Repository會包裝NHibernate會話。此存儲庫可以是每個類(So CustomerRepository和OrderRepository),或者如果您的域中沒有太多的類,則也可以從單個存儲庫開始。

這是放置Criteria查詢(LoadAllByName,LoadCustomerWithOrder等)的理想場所。如果您以後需要切換到不同的ORM或甚至不同的持久性機制(非常少見,我認爲),則可以交換包括Repository在內的整個數據層。

0

查詢屬於存儲庫。您可能在任何需要的地方爲GetCustomersPossiblyInterestedIn(Product p)提供函數簽名,但查詢本身只應在存儲庫類中

1

當然,請避免將面向對象的查詢放入表示層。它應該只顯示/使用從業務邏輯層(BLL)接收的數據。沒有任何查詢。如果您需要查詢從BLL收到的結果,則需要擴展BLL以提供無需查詢的數據。

您的想法是使用「面向對象的查詢語言」接縫。通常情況下,這種「語言」是你的DAL :)我會說的很好的例子,‘面向對象查詢語言’是一個正確實現數據訪問層(DAL)。

從我的角度來看,你DAL應該實現80-90所有功能%和提供一套功能類似:

  • 客戶GetCustomerById(INT客戶ID);
  • 列表GetLastRegisteredCustomers(INT計數);
  • 等...

這些函數提供了不需要查詢的所需功能的最大部分。

對於所有其他10-20%很少使用的查詢(您將它們命名爲「面向對象」),您的DAL應該實現返回IQueryable結果的方法/方法,我會說至少是'GetAll()'方法並且可能很少定製:

  • IQueryable GetAll();
  • IQueryable GetCustomerByCountry(int countryId);
在這種情況下

,如果你需要找到一個國家的客戶登記今年你BLL你撥打:

List<Customer> customers = GetCustomerRepository() 
    .GetCustomerByCountry(countryId) 
    .Where(customer=>customer.RegisterDate.Year==year) 
    .ToList<Customer>() 
    ; 

猜,你知道什麼提供的IQueryable <>接口。

如何在NHibernate下使用Linq:Linq to NHibernate

一個額外的提示:我會建議爲您的DAL實現使用'Repository'模式。前一段時間,我用這個想法:http://habrahabr.ru/blogs/net/52173/(如果你不能閱讀俄文翻譯整個網頁 - 它應該是可讀的)。

希望有所幫助。

+0

那麼,你會拆分DAL和BAL之間的複雜查詢嗎? 我不太熟悉Linq/Linq到NHibernate。 GetCustomerByCountry(int)會返回什麼?內存中的所有客戶對象? – 2010-09-23 15:24:56

+0

var customersByCountry =「GetCustomerByCountry(int)」將返回一個「查詢對象」。這是一個表達式,當你調用諸如customersByCountry.Fisrt(),customersByCountry.ToList()等等時,將由DATABASE執行。但是在調用.ToList()之前,你可以調用'Where'擴展方法來應用附加條件在您的查詢中也將由DB執行。我建議使用你的數據庫分析器來查看什麼和什麼時候被真正執行以更好地理解正在發生的事情。如果您有更多問題,請告訴我,但這可能是另一個話題。 GL! – Budda 2010-09-23 16:00:37

+0

謝謝!假設你不能使用Linq(例如,在Java中),你怎麼能做到類似的東西?有沒有一個命名的設計模式是由Linq實現的,你描述的NHibernate方法? – 2010-09-26 20:55:59