2011-09-21 92 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

相关问题