2011-09-21 144 views
11

這裏是真實的例子,將導致我的問題:我有一個AddCommentToArticleCommand,它有一個ArticleId,評論文本和電子郵件地址。這條命令:保存域實體更改

  • 使用的物品儲存庫以獲取文章(這是域實體)是否存在文章
  • ,它調用article.AddComment(commentText,EMAILADDRESS),它增加了評論文章和拋出異常,當它不能(由於無效的電子郵件格式,文章被關閉,評論沒有填寫或太長等...)
  • 但現在我不知道什麼是最好的方法是保存添加評論?

我應該做一些像articleRepository.Save(文章)?但是,如果只添加評論,爲什麼我應該保存文章?或者我可以做些像articleRepository.SaveComment(評論),只會保存評論?或者你會採取什麼方式?

謝謝!

回答

8

由於MattDavey指出,在DDD你平時想Aggregate生命週期,不是CRUD持久性問題。彙總的中期和結束時間由相應的Repository處理。關於你的具體問題:

但現在我不知道什麼是最好的方式來保存添加評論?

處理這種情況最好的辦法是找到一個可靠的ORM和使用這個ORM實現你

articles.MakePersistent(article) 

庫方法。好的ORM將實現UnitOfWork,將包括髒跟蹤,延遲加載和其他持久性相關問題,而不會限制您的域對象。 當保存聚合時,ORM知道如何避免不需要的SQL INSERT/UPDATE。你的域對象應該儘可能地永遠無知。例如,NHibernate唯一的限制就是你的對象應該有私有的默認構造函數。除此之外,它們可以是簡單的POCO對象,不知道所有持久性問題。爲了清除,域對象不應該有IsTransientIsDirty標誌。如果你發現自己編寫使用這些標誌的代碼,你是reinveting the wheel

+2

你幫我評論過,因爲我意識到我正在做的事情已經存在。所以我改變了方法:我首先使用代碼實體框架;並實行工作單位模式。所以現在EF環境正在爲我保留這些變化。感謝您的反饋! –

+0

@Dmitry +1這是一個非常有效的點。在我的特殊情況下,我不能對所使用的ORM的功能做任何假設(它甚至可能不是ORM),因此我有必要在域中實現諸如更改跟蹤等事情。如果你充分綁定到一個ORM實現,你可以可靠地利用它的功能,那麼當然這樣做很有意義:) – MattDavey

+0

實際上,我的域不依賴於ORM或其他任何東西。這是洋蔥建築的中心。圍繞它構建的工作單元依賴於ORM,並使用其上下文進行更改跟蹤。但該域名只有域邏輯... –

1

在DDD中,通常情況下,您將聚合根下的整個組合層次結構向下並將其視爲單個實體。所以,採用這種心態,「如果只添加評論,我爲什麼要保存文章?」,整篇文章似乎已經發生了變化,並且文章在數據庫中的表示形式已過時。理想情況下,您可以替換數據庫中的整個組合層次結構(使用文檔數據庫這樣可以),但這可能會導致關係數據庫中的性能問題。

在這種情況下,您可能決定讓存儲庫掃描實體組合,聚合根,並智能決定如何處理每個組件。您可以使用訪問者模式遍歷Comment對象,並根據它們是否爲瞬態/髒,決定進行插入或更新,或者僅僅讓它們獨立。

我希望我已經一直不夠清晰,我不太擅長解釋概念性的東西:)

編輯:代碼示例:

// In ArticleRepository... 
public void Save(Article article) 
{ 
    // IsTransient (as opposed to IsPersistant) means "has not yet been saved"... 
    if (article.IsTransient) 
    { 
     DB.InsertArticle(article); 
     // Inserting the article also inserts any comments/sub components... 
    } 
    else 
    { 
     // IsDirty means "has been modified since it was taken from the DB"... 
     if (article.IsDirty) 
     { 
      DB.UpdateArticle(article); 
     } 

     foreach(var comment in article.Comments) 
     { 
      if(comment.IsTransient) 
      { 
       DB.InsertComment(article.Id, comment); 
      } 
      else 
      { 
       if (comment.IsDirty) 
       { 
        DB.UpdateComment(comment); 
       } 
      } 
     } 
    } 
} 
+0

謝謝!所以我想這意味着如果屬性改變,實體應該更新這些IsTransient和IsDirty屬性;並且存儲庫負責在保存實體後重置它們? –

+0

的確,請查看System.ComponentModel.IChangeTracking接口。 IsTransient/IsPersistant有時可以通過缺少/存在主鍵值分別推斷出來。 – MattDavey

+0

在我的實體中,我經常也實現ISupportInitialize,當實體被初始化時,更改屬性不會使實體變髒(或提高屬性改變事件等)。這可以是非常方便的:) – MattDavey

相關問題