保存域实体更改
本文关键字:实体 保存 | 更新日期: 2023-09-27 18:09:06
这是一个真实的例子,将导致我的问题:我有一个AddCommentToArticleCommand,它有一个ArticleId,评论文本和电子邮件地址。这个命令:
- 使用文章存储库获取文章(这是域实体)
- 如果article存在,则调用article。AddComment(commentText, emailAddress),它将评论添加到文章中,并在无法(由于无效的电子邮件格式,文章已关闭,评论未填写或太长等)时抛出异常
- 但是现在我不知道保存添加评论的最好方法是什么?
我应该做一些像articlerrepository . save (article)这样的事情吗?但是,如果只添加了评论,我为什么要保存文章呢?或者我可以像articlerrepository。savecomment (comment)那样,只保存评论?或者你会采取什么方法?
谢谢!
正如MattDavey指出的那样,在DDD中,您通常考虑聚合生命周期,而不是CRUD持久性问题。聚合的生命周期中期和末期由相应的存储库处理。关于你的具体问题:
处理这个问题的最好方法是找到一个可靠的ORM并实现你的但是现在我不知道保存添加的注释的最好方法是什么?
articles.MakePersistent(article)
使用此ORM的存储库方法。好的ORM将实现UnitOfWork,将包括脏跟踪,延迟加载和其他持久性相关问题,而不会限制你的领域对象。ORM知道如何在保存聚合时避免不需要的SQL INSERT/UPDATEs。您的域对象应该尽可能地持久无知。例如,NHibernate对对象的唯一约束是它们应该有私有的默认构造函数。除此之外,它们可以是不知道所有持久性问题的简单POCO对象。只是为了澄清,域对象不应该有IsTransient
或IsDirty
标志。如果您发现自己编写的代码使用了这些标志,那么您就是在重新发明轮子。
在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);
}
}
}
}
}