2010-06-05 56 views
1

目前,我們使用NHibernate將業務對象映射到數據庫表。所述業務對象執行業務規則:如果違反了該屬性的合同,則集訪問者將在現場拋出異常。此外,這些屬性還會強制執行與其他對象的關係(有時是雙向的!)。那麼,只要NHibernate從數據庫加載一個對象(例如,當調用ISession.Get(id)時),映射屬性的set訪問器將用於將數據放入對象中。我應該用NHibernate映射哪些類?

好的是應用程序的中間層強制執行業務邏輯。有什麼不好的是數據庫沒有。有時候廢話會進入數據庫。如果垃圾被加載到應用程序中,它會釋放(拋出異常)。有時顯然應該保釋,因爲它什麼都不能做,但如果它能繼續工作會怎麼樣?例如,收集實時報告的管理工具存在不必要地失敗的高風險,而不允許管理員甚至修復(潛在的)問題。

我現在還沒有一個例子,但是在某些情況下,讓NHibernate使用同樣強制關係的「前門」屬性(特別是bidi)會導致bug。

什麼是最佳解決方案?

目前,我公司將在每個屬性的基礎上,創建一個「後門」只爲NHibernate的:

public virtual int Blah {get {return _Blah;} set {/*enforces BR's*/}} 
protected virtual int _Blah {get {return blah;} set {blah = value;}} 
private int blah; 

我發現在C#2(無默認屬性)以上來說明它如何獲得我們基本上3層,或意見,以免!雖然這當然有效,但它看起來並不理想,因爲它要求BL爲數據訪問層提供一個(公共)接口用於應用程序,另一個(受保護)接口。

還有一個額外的問題:據我所知,NHibernate沒有給你一種方法來區分BL中的屬性名稱和實體模型中的屬性名稱(即你使用的名稱查詢,例如通過HQL - 每當你給NHibernate一個屬性的名稱(字符串))。首先,BR的某些屬性Blah沒有問題,因此在您的O/R映射中引用它時,這會成爲一個問題......但是之後,您必須添加一些確實成爲問題的BR,所以那麼你必須改變你的O/R映射來使用一個新的_Blah屬性,該屬性使用「Blah」打破所有現有的查詢(對照字符串進行編程的常見問題)。

有沒有人解決了這些問題?

+2

它爲什麼你不能阻止進入你的數據庫無效數據目前尚不清楚。我不認爲這種情況下有一個通用的解決方法(不管是否涉及NHibernate)。你可能會不斷地輪詢數據庫尋找無效數據,然後在NHibernate嘗試加載它之前嘗試糾正它。 – 2010-06-05 09:43:37

+0

剛剛找到相關的討論:http://stackoverflow.com/questions/129773/nhibernate-map-to-fields-or-properties – apollodude217 2010-06-07 16:04:58

+0

@Michael:好問題/評論。通常,這是一個傳統的應用程序,預先存在的數據不符合業務需求(我知道我們應該清理它),或者其他傳統應用程序允許不良數據進入的地方。 – apollodude217 2010-06-07 18:30:16

回答

3

雖然我發現大部分架構存在問題,但處理這些東西的通常方法是讓NHibernate使用後臺字段而不是setter。

在上例中,您不需要定義額外的受保護屬性。只是在映射使用:

<property name="Blah" access="nosetter.lowercase"/> 

這是在文檔中描述,http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-property(表5.1訪問策略)

+1

這實際上是Hibernate的首選訪問策略:業務規則應該從數據庫中讀取時不會被強制執行,您應該獲取其中的內容。 出於某種原因,NHibernate的人不同意並提倡/推薦物業訪問策略。 – 2010-06-05 21:32:08

+1

@Fried,這可能是因爲setter通常不是使用.NET/NHibernate強制執行規則的地方。實際上,大多數持久實體使用自動屬性,因此會生成getter/setter主體。 – 2010-06-05 22:49:18

+0

感謝您的意見! @Diego, 在我看來,這個解決方案將削減對C#2代碼(只是屬性和字段)Blah的意見。但在C#3中,它會要求我有兩層(屬性和字段) - 即Blah不能是默認屬性;無論是否存在任何業務邏輯,它都必須用手編碼。我理解正確嗎? – apollodude217 2010-06-07 15:29:40