【问题标题】:DDD: guidance on updating multiple properties of entitiesDDD:更新实体多个属性的指南
【发布时间】:2015-11-13 17:11:23
【问题描述】:

所以,我决定学习 DDD,因为它似乎可以解决我一直面临的一些架构问题。虽然有很多视频和示例博客,但我还没有遇到可以指导我解决以下场景的内容:

假设我有实体

public class EventOrganizer : IEntity
{
    public Guid Id { get; }

    public string Name { get; }

    public PhoneNumber PrimaryPhone { get; }

    public PhoneNumber AlternatePhone { get; private set; }

    public Email Email { get; private set; }

    public EventOrganizer(string name, PhoneNumber primaryPhoneNr)
    {
        #region validations

        if (primaryPhoneNr == null) throw new ArgumentNullException(nameof(primaryPhoneNr));

        //validates minimum length, nullity and special characters
        Validator.AsPersonName(name);

        #endregion

        Id = new Guid();
        Name = name;
        PrimaryPhone = primaryPhoneNr;
    }
}    

我的问题是:假设这将被转换并提供给 MVC 视图,并且用户想要更新 AlternatePhone、电子邮件和许多其他属性,这些属性对于给定的有界上下文(不是为简洁起见)

我知道正确的指导是为每个操作都有一个方法,但是(我知道它有点像反模式)我不禁想知道这是否最终会触发数据库上的多个更新调用。

这是如何处理的?在某个地方,是否会有一些东西将我的 EventOrganizer 映射到某个东西 - 比如 DbEventOrganizer 并收集对域实体所做的所有更改并一次性应用这些更改?

【问题讨论】:

    标签: c# .net domain-driven-design software-design


    【解决方案1】:

    DDD 更适合基于任务的 UI。您描述的内容非常面向 CRUD。在您的情况下,单个属性被视为独立的数据字段,其中一个或多个可以通过单个通用业务操作(更新)进行更新。

    如果您想成功使用 DDD,则必须对您的域进行更深入的分析。

    为什么有人会一起更新所有这些字段?用户试图通过这样做来实现什么隐含的业务操作?有没有更具体的业务流程,通过同时更改PrimaryPhoneAlternatePhoneEmail 来表达?

    也许这正在改变EventOrganizerContactInformation?如果是这种情况,那么您可以在EventOrganizer 上模拟单个ChangeContactInformation 操作。然后,您的 UI 将发送 ChangeContactInformation 命令而不是 update 命令。

    至于聚合根 (AR) 的持久性,如果您使用的是 RDBMS,这通常由像 NHibernate 这样的 ORM 处理。但是,还有其他方法可以持久化您的 AR,例如 Event Sourcing、NoSQL DB 甚至 storing JSON 或 RDBMS 中的任何其他数据交换格式。

    【讨论】:

    • 谢谢。虽然我需要对我的领域进行更深入的分析,但这正是我所需要的;我真的需要一个 ChangeContactinformation 操作,只是这是我的第一个 DDD 项目,我被我以 CRUD 为导向的头脑所吸引。非常感谢!
    • @Sergio 我很高兴能帮上忙!需要明确的是,ContactInformation 应该是一个值对象。不要将 PrimaryPhone、Email 等单个 VO 作为单独的参数传递给 ChangeContactInformation 方法。
    【解决方案2】:

    你的问题很宽泛!

    EventOrganizer 本身不应更新任何内容。您应该将更新代码与实体完全分开。不同的类将采用 EventOrganizer 对象并更新数据库。这称为“持久性无知”,使代码更加模块化和内聚。

    创建 View Model 是很常见的 - 一个类,其目的是为 View 提供它需要的确切数据,以它需要的确切形式。您需要从 EventOrganizer 创建视图模型,之后视图可以更新它 - 以编程方式或通过绑定。当您准备好保存更改时,您需要从 View Model 更新 EventOrganizer 并将其传递给更新程序。当项目小而简单时,这似乎是您不需要的层,但随着复杂性的增加,它变得非常宝贵。

    【讨论】:

    • 我的观点是,因为我用一个方法一次更新一个属性,在一个有人更新说 10 个属性的场景中,这 10 个单独的更新如何与我在 EventOrganizer 上的单独方法相关,然后到只有一条sql更新指令?
    • 在实体上设置属性不需要包装在方法中,除非实体需要知道属性更改。像 EventOrganizer 这样的实体没有太多的内部逻辑,所以直接设置它的属性就可以了。除非您正在实施某种审计,否则您不需要知道哪些属性已更改 - 不需要在该级别进行跟踪。相反,您可以一键将整个实体写回数据库 - 包括未更改的属性。或者编写你的 SQL 来检查新值和旧值,只写有变化的部分。
    • 我建议查看像实体框架或 nHibernate 这样的 ORM 框架。您不需要编写 SQL 语句,只需更新对象并告诉 ORM 更新数据库。
    • 他们解释将 ViewModel 绑定到域对象的方式是 CRUDish。这不是它在实践中的工作方式。您的 ViewModel 可用于捕获有关特定命令的信息并在 UI 上验证该命令。但是,一旦控制器接收到 VM,它应该将其分解为 ApplicationService 可以理解的命令。然后 ApplicationService 将负责在适当的聚合根上调用命令。 VM 和聚合根之间没有属性到属性的映射。
    • 公平评论 - 我过于简单化了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 2017-09-04
    • 2012-02-20
    • 1970-01-01
    相关资源
    最近更新 更多