保存域实体更改

发布于 2024-12-05 19:28:41 字数 442 浏览 0 评论 0原文

这是引出我的问题的真实示例:我有一个 AddCommentToArticleCommand,其中包含 ArticleId、评论文本和电子邮件地址。该命令:

  • 使用文章存储库获取文章(即领域实体),
  • 如果文章存在,它调用article.AddComment(commentText, emailAddress),它将评论添加到文章中,如果不能添加评论,则抛出异常(由于电子邮件格式无效、文章已关闭、评论未填写或太长等...)
  • 但现在我不知道保存添加的评论的最佳方法是什么?

我应该做类似articleRepository.Save(article) 的事情吗?那么,如果只添加了评论,为什么还要保存文章呢?或者我可以做类似articleRepository.SaveComment(comment)之类的事情,这只会保存评论吗?或者你会在这里采取什么方法?

谢谢!

here's real example that will lead to my question: I have an AddCommentToArticleCommand, which has an ArticleId, comment text and email address. This command:

  • uses the article repository to get the article (which is the domain entity)
  • if article exists, it calls article.AddComment(commentText, emailAddress), which adds the comment to the article and throws exception when it can't (due to invalid email format, article was closed, comment not filled in or too long etc...)
  • but now I don't know what the best way is to save the added comment?

Should I do something like articleRepository.Save(article)? But then, why should I save the article if only a comment was added? Or can I do something like articleRepository.SaveComment(comment), that will only save the comment? Or what approach would you take here?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一个人练习一个人 2024-12-12 19:28:41

正如 MattDavey 指出的那样,在 DDD 中,您通常会考虑 聚合生命周期,与 CRUD 持久化问题无关。聚合生命周期的中期和结束由相应的存储库处理。关于您的具体问题:

但现在我不知道保存添加的评论的最佳方法是什么?

处理这个问题的最佳方法是找到一个可靠的 ORM 并

articles.MakePersistent(article)

使用这个 ORM 实现您的存储库方法。好的 ORM 将实现 UnitOfWork,将包括脏跟踪、延迟加载和其他与持久性相关的问题,而不受约束你的域对象。 ORM 知道如何在保存聚合时避免不需要的 SQL INSERT/UPDATE。您的领域对象应该尽可能保持无知。例如,NHibernate 对对象施加的唯一限制是它们应该具有私有的默认构造函数。除此之外,它们可以是简单的 POCO 对象,不知道所有持久性问题。需要澄清的是,域对象不应具有 IsTransientIsDirty 标志。如果您发现自己编写的代码使用了这些标志,那么您就是在重新投入

As MattDavey points out, in DDD you usually think about Aggregate life cycle, not about CRUD persistence issues. The middle and end of life of the Aggregate is handled by a corresponding Repository. Regarding your specific question:

but now I don't know what the best way is to save the added comment?

The best way to handle this is to find a reliable ORM and implement your

articles.MakePersistent(article)

repository method using this ORM. Good ORM will implement UnitOfWork, will include dirty tracking, lazy loading and other persistence related issues without constraining your domain objects. ORM knows how to avoid not needed SQL INSERT/UPDATEs when saving the Aggregate. Your domain objects should be as persistent ignorant as possible. The only constraint that NHibernate, for example, puts on your objects is that they should have private default constructor. Other than that they can be simple POCO objects unaware of all the persistence issues. Just to clear, domain objects should not have IsTransient or IsDirty flags. And if you find yourself writing code that uses these flags you are reinveting the wheel.

仲春光 2024-12-12 19:28:41

在 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);
                }
            }
        }
    }
}

In DDD it's often the case that you take the entire composition hierarchy from the aggregate root down and treat it as a single entity. So, adopting that mentality, "why should I save the article if only a comment was added?", it would seem that the article as a whole has changed, and the representation of the article in the database is stale. Ideally you would replace the whole composition hierarchy in the database (with a document database this would be fine), however this could lead to performance problems in a relational DB.

In that case you might decide to have the repository scan over the composition of the entity, aggregate root down, and intelligently decide what to do with each component. You could use the visitor pattern to iterate through the Comment objects, and depending on whether or not they are transient/dirty, decide to do an insert or update, or just to leave them alone..

I hope I've been clear enough, I'm not so good at explaining conceptual things :)

EDIT: Code sample:

// 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);
                }
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文