2011-08-11 78 views
4

我正在學習DDD(域驅動設計)和存儲庫模式(在C#中)。我希望能夠使用存儲庫模式來堅持一個實體,而不關心實際使用哪個數據庫(Oracle,MySQL,MongoDB,RavenDB等)。但是,我不確定如何處理數據庫特定的ID:大多數(所有?)數據庫使用的數據庫。例如,RavenDB要求它應該存儲的每個實體都有一個字符串類型的id屬性。其他可能需要一個int類型的id屬性。由於這是由不同的數據庫處理不同,我不能使數據庫ID成爲實體類的一部分。但是至少當我存儲實際的實體時,它必須在某個時刻存在。我的問題是關於這方面的最佳做法是什麼?使用存儲庫模式抽取數據庫特定的id:s?

我目前正在追求的想法是,對於我想要支持的每個數據庫,爲每個業務對象類型實現特定於數據庫的「值對象」。這些值對象然後將具有數據庫特定的id屬性,並且我會在讀取和寫入之間映射兩者之間的映射。這似乎是一個好主意嗎?

+1

你真的需要它嗎?對於我來說這似乎不是個好主意,因爲你會遇到維護地獄。 – xelibrion

+0

我同意xelibrion在這裏。 – NotMe

+0

我正面臨同樣的問題。不幸的是,這裏提到的解決方案中沒有一個將我描述爲「完美的解決方案」(如果有的話......)。我也考慮過轉換爲數據抽象層中的特定實現類型。我的意思是,雖然'DTO'和'DAO'是所有DB類型通用的接口,但任何特定的'DAO'實現都會將方法內的'DTO'轉換爲相同的特定實現類型假設一次只使用一種數據庫類型)。這樣,它將能夠使用特定的ID。這看起來很骯髒,但這是我迄今爲止最好的。 – eitanfar

回答

0

您可能在實體中擁有該ID,但不會將其作爲實體公共接口的一部分公開。這對NHibernate來說是可能的,因爲它允許你將表格列映射到一個專用字段。

所以,你都可能有類似

class Customer { 
     private readonly Int32? _relationalId; 
     private readonly String? _documentId; 
     ... 

這不是理想的,因爲你的持久邏輯「流血」的業務邏輯,但給出的要求很可能是比實體之間保持映射更簡單,更健壯的實體之外的某處。我還強烈建議您評估「數據庫不可知」方法,如果您只想支持關係數據庫,那麼這種方法更爲實際。在這種情況下,您至少可以重複使用像NHibernate這樣的ORM來存儲庫實現。而大多數關係數據庫都支持相同的id類型。在你的場景中,你不僅需要ORM,還需要諸如「Object-Document-Mapper」之類的東西。我可以看到你將不得不編寫大量的基礎設施代碼。我強烈建議您重新評估您的要求,並在關係數據庫和文檔數據庫之間進行選擇。閱讀原文:Pros/cons of document-based databases vs. relational databases

3

這是泄漏抽象的經典案例。除非你想放棄每個數據庫帶來的所有好處,否則你不可能在存儲庫接口下抽象出數據庫的類型。關於身份證類型(字符串,Guid或其他)的要求只是在渾水中擁有大部分質量的巨大冰山的頂部。

想想事務處理,併發和其他的東西。我理解你關於持久性無知的觀點。在域模型中不要依賴特定的數據庫技術是一件好事。但是你也無法擺脫對任何持久性技術的依賴。

讓你的領域模型適用於任何RDBMS是相對容易的。他們大多數都有標準化的數據類型。使用像NHibernate這樣的ORM將會幫助你很多。在NoSQL數據庫中實現這一點很難,因爲它們往往有很大差異(實際上這非常好)。

所以我的建議是對可能的持久性技術集合進行一些研究,然後爲持久性子系統選擇適當的抽象級別。

如果這不適合您,請考慮事件採購。事件存儲是最不苛刻的持久性技術之一。使用Jonathan Oliver的等庫可以讓您幾乎使用任何存儲技術,包括文件系統。

+2

不,這是相反的 - 避免泄漏抽象的經典案例。使用商店的ID類型作爲對對象的全局「友好」參考是有漏洞的。讓商店堅持認爲ID是好的,通常是必要的。通常情況下,這兩件事情是一致的。本章試圖將兩者分開,因此他必須解決這個問題。 – Chalky

+0

@Chalky我同意你的觀點,當涉及到主要的API提供者(比如數據庫)時,(幾乎總是)沒有太多的抽象。如果您非常依賴數據庫類型,以至於您在代碼中的任何地方都使用特定的ID類型,那麼您將無法將數據庫更改爲...以及幾乎永遠不會!一旦數據庫充滿數據,公司不願意替換他們正在使用的數據庫,這在很大程度上也是因爲大部分時間,這也意味着提供了一個全新的軟件實現,這是由於假設一個特定的ID類型。 – eitanfar

1

我會繼續並在實體中創建一個int Id字段,然後將其轉換爲存儲庫中Id必須是字符串的字符串。我認爲,抽象持久性的努力是非常值得的,並且實際上可以簡化維護工作。

1
  1. 你正在做正確的事情!將自己從數據庫主鍵類型的約束中抽象出來!

  2. 不要嘗試翻譯類型,只是使用不同的字段。

特別是:不要嘗試使用數據庫的主鍵,除了在您的數據訪問邏輯。如果你需要一個友好的對象ID,只需創建一個你喜歡的任何類型的附加字段,並且需要你的數據庫來存儲它。只有在你的數據訪問層,你需要找到&根據你的對象的友好ID更新數據庫記錄。簡單。

然後,您對哪些數據庫可以持久保存對象的約束已從'必須能夠具有xxxx類型的主鍵'變爲'必須能夠存儲類型xxxx'。我想你會發現你可以使用世界上任何數據庫。快樂的編碼! DDD是最好的!

+0

我在問題中也遇到同樣的問題。你的建議是我想到的第一件事。唯一讓我感到困惑的是,它可能會在數據庫中的任何對象中創建兩個不同的ID類型字段。 – eitanfar