2011-03-29 67 views
3

我努力在.net解決方案中使用DDD實現一項要求。我會盡量減少細節:如何實現DDD存儲庫來處理具有多個實體的查詢?

實體:

  • 類別(UID,名稱)
  • 屬性(UID,名稱,AttributeValues [])
  • 的AttributeValue(UID,名稱,ParentAttributeUId )
  • 過程(UID,名稱,AttributeValues [],分類[])

數據模型:

  • 每個進程可以有多個類別(例如, ProcessCategoryMap表)
  • 每個過程可以有多個AttributeValues(例如ProcessAttributeValue表)
  • 類別之間沒有關係,屬性,attributeValues

我有S.P. FetchByCategoryAndAttributeValues(類別ID,AttributeValueIds []) 返回一個數據集:

  • 匹配類別ID過程的列表中,而且可用AttributeValueIds細化搜索AttributeValues的
  • 列表。

如何實現存儲庫加上調用SP的方法,當返回多個實體時,在我看來,返回的對象是一個值對象,它似乎不在現有實體存儲庫中引用?

什麼想法?

問候,

佩德羅

====編輯:2011/03/30下午2時52 UTC ====

我更新我的問題,珍惜所有的意見加上幫助其他人面臨類似的挑戰。

@Justice:

解決方案:使用ORM例如NHibernate加上使用ORM的所有理由

我不記得任何在Eric Evans ddd書中提到的ORM。具體的持久性技術如何選擇呢?一旦你清理了域名,你就可以隨心所欲地堅持下去。 Offcourse我知道NH可以提供幫助並且是強大的工具,但它本身不是解決方案。

@Dominic/@Justice:

解決方案:從存儲過程的移開。

首先,對於我來說很難證明當我看到好的T-SQL存儲過程時,我不是在談論CRUD或簡單的T-SQL查詢。我提到的SP運行幾個TSQL CTE,結合不同表中的度量數據來計算權重,使用臨時表並返回客觀結果:進程列表,類別列表,屬性值列表。對SP進行優化和調整爲特定的SQL數據庫/服務器可能是一個MSFT,Oracle等我不相信那些轉移到計算應用端,然後在ORM依賴將有助於執行時間加上所有回並轉發查詢。對於我來說,在服務器中完成所有這些工作並僅引入過濾數據有很大的區別。我可能是錯的。

@All: 我已經確定了真正的問題(如Domenic指出了與ayende鏈接)我正在將一種基於數據中心方法的解決方案移植到域模型方法中。讓我們把它放回去,由SP返回的計算會影響不同的模型。由於數據在數據庫中的存在方式,常見的計算和計算在實體之間是有界的,所以問題在於如何實現DDD實現時如何獲得最佳效果。以及如何保持數據庫管理員的工作:)

您可以創建一個非常好的域模型,堅持數據跨越N個不同的表,問題是當您查詢該數據如何使模型,並保持DDD處於良好的立場。

謝謝大家,我還在尋找創意,答案等:)

問候, 佩德羅

+0

剛剛看到您的更新。是的,保持DBA的工作是我們在最後一個地方努力奮鬥的事情:P – Domenic 2011-04-17 05:42:39

回答

4

你眼前的問題是如何將在包含一些數據,以及一些「不相關」的數據,允許對數據進行與域模型一致的方式進一步過濾的數據集。

之所以這是一個問題,因爲這個概念 - 帶過來源性或外周相關數據的多個表不與域建模確實是一致的。領域建模是關於定義包含核心應用程序基本領域知識的關係和複雜業務邏輯。不產生基本相關對象的多個表格意味着它可能不是開始的領域模型的一部分。

如果您沒有天生適合您正在嘗試做的事情的對象,則意味着您的模型不完整,或者在這種情況下可能是因爲您試圖將應用程序的用戶界面方面泄漏到域中模型。可能是後者。

解決方案還包括像MVP或MVC這樣的用戶界面視圖體系結構。域對象是關於跨業務執行業務規則的 - 保存和更新。例如,使用DTO和Presenters來組裝任何類型的「新」或「混合」對象,這些對象不代表核心領域知識,而是構造成以某種用戶想要的方式向用戶呈現數據。

在這種情況下,您只需創建一個DTO,將Process和Attribute DTO合併到一個新對象中供UI使用。

但也有一些其他的可能性:

1)有,當你有,如果你甚至使用了合適的工具來問自己的時間。我正在研究一個具有非常複雜的域模型的醫療應用程序。這是核心應用程序 - 在整個數據採集過程中執行復雜的規則。但是,一旦獲得這些數據,企業就有興趣用它做很多不同的事情。採集模型和分析模型並不完美,所以不要試圖讓它們一起工作,我認爲選擇採用DDD的採集模型然後使用ETL並將數據移動到數據倉庫中是更好的選擇,給企業一個單獨的分析應用程序,這是建立在查詢上的,而不是OOP/DDD。

2)領域建模是關於定義反映真實領域的模型,而不是關於關係數據技術。其目標是管理複雜性並創建一個既可以隨着業務變化而改進又可以發展的模型。你不會發現很多人在做很多DDD,甚至會假裝優化是其中的一個方面。相反,你儘可能地建立一個與DDD一致的模型。如果以後你必須儘可能多地折衷該模型,以便將不可接受的性能帶入可接受的範圍。

有很多很多事情可以用更高效的查詢來完成。當然,如果有人根本不知道應用程序,他們可能需要跟蹤一堆這些東西,並且很可能必須或多或少地理解整個應用程序,然後才能理解這些應用程序。 DDD可以使人們成功地完成某些工作,但他們對應用程序的其餘部分幾乎一無所知,但在性能或往返方面您甚至沒有任何事情達到最佳狀態。

既然它看起來非常有吸引力和合乎邏輯,爲了實現兩全其美的目的,我會像ETL和數據倉庫那樣硬核SQL的東西,並且我會做DDD。我對你如何成功地將兩個世界合併到一個應用程序中存在一些疑問。不是兩全其美的,你最終可能會得到一個沒有人可以使用的應用程序,而且性能也不好。如果你有一堆有效的存儲過程,那裏肯定會有一堆業務邏輯。如果你還有「對象」有業務邏輯,那麼你最終得到的是數據庫中的業務邏輯,「對象模型」中的業務邏輯變成只是(又一個)有類的應用程序,但不是OOP或DDD - 幾乎與人們多年來一直在做的一樣,稱它爲「n層」。

不要誤解我的意思 - DDD應用程序仍應建立在堅實的數據庫和關係原則基礎之上,並且性能沒有任何問題。但是很多數據庫服務器處理實際上都將域活動泄漏到數據庫中。此外,很多這些最佳數據處理技術都違反了OOP和DDD的多重原則。

如果你不願意完全放棄所有的數據庫內容,並且它對你來說工作的很好,那麼你可能不需要甚至不想移動到DDD概念。如果你想要DDD,最​​好的方法是考慮你擁有的所有東西作爲寶貴的領域知識的來源,但是在實施細節方面,遺留代碼正在被完全拋棄。 DDD並不適合將一個無DDD應用程序「移植」到。

1

使用NHibernate的。

讓ORM 你的資料庫。這就是它的目的。

+0

感謝您的評論,但對我而言,事情的美妙之處在於符合簡單性。我有很多很好的T-SQL sps來完成這項艱苦的工作。我很想在ORM之外尋找解決方案。 – 2011-03-29 21:02:58

+0

像NHibernate一樣的ORM *易於使用*和*強大*。您很可能不需要存儲過程,任何複雜的域邏輯都可以輕鬆地作爲實例/靜態模型方法來處理。當你沒有強大的工具時,存儲過程是一個柺杖。 – yfeldblum 2011-03-30 00:11:41

+0

相關:http://ayende.com/Blog/archive/2009/08/15/the-least-common-denominator-approach.aspx – Domenic 2011-03-30 12:18:58

3

你需要以某種方式抽象的持久性代碼。屬於在基礎結構層,而不是在域層(參見DDD第68頁)。你可以手動完成這些工作,編寫代碼用DataSet或者使用像NHibernate這樣的ORM。

如果您要手動執行此操作,我建議的模式與C#中Martin的Agile模式,實踐和原則中的工資案例研究中探討的模式類似。第569頁的圖表顯示了他如何打包組件。

+0

感謝您的意見,我沒有問題的堅持,那是由Process Repository處理。問題是如何處理直接提取不相關實體的SP。關於這本書,我會看看我想你提到第35章:訪客。與DDD書相關的是關於基礎設施層的權利? – 2011-03-29 21:36:07

+0

用於從數據庫中提取事物的SP是持久性代碼,不應直接從您的域層調用。由於存儲庫位於您的域圖層中,因此您似乎有一個相當致命的缺陷...... – Domenic 2011-03-30 01:09:43

0

如果你已經在使用實體框架,有幾個方法可以做到這一點(這個答案已經與佩德羅的重疊),每個都有自己的侷限性&使用情況:

  1. 查詢EF實體和回報DTO的。
  2. 直接使用DBContext的Database.SqlQuery查詢SQL。如果您的DTO屬性名稱與您的SQL列匹配,那麼它會爲您映射它們。