首页 > 解决方案 > CQRS DDD - 命令和领域模型的关系

问题描述

我正在练习使用 CQRS 和 DDD 尽我所能来实施一个项目,并且在构建命令后提出了一个问题。

场景:用户发送命令在系统中创建一个书架,该书架本身也可以包含书籍集合。

该命令如下所示:

public class CreateNewBookShelfCommand : ICommand
{
    public long CommandInitiatorId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public ICollection<Book> Books { get; set; }
}

所有Commands驻留在解决方案文件夹Contracts内的项目中。Application

位于解决方案文件夹中的Model项目Domain托管BookShelf实体类,其中包括书籍集合。

问题1: 上面的命令有这个Books类型的属性Book。我的问题是:Commands项目是否应该直接引用 Model 项目,以便BookCreateNewBookShelfCommand? 我自己,我不认为Contracts允许引用除 theCommandHandlers或任何其他可能是Cross Cut的项目之外的任何项目。

问题 2:那么,在项目中复制部分Book实体类并在?ContractsCreateNewBookShelfCommand

这是我的模型项目,Book并且BookShelf

public class BookShelf : BaseEntity
{
    public string Name { get; set; }
    public string Description { get; set; }
    public BookShelfAccess Access { get; set; }

    public virtual BookShelfOwner Owner { get; set; }
    public long OwnerId { get; set; }

    public ICollection<Book> Books { get; set; }
}

 public class Book : BaseEntity
{
    public string Name { get; set; }
    public DateTime? PublishedAt { get; set; }
    public int NumberOfPublishes { get; set; }

    public virtual BookShelf Shelf { get; set; }
    public long ShelfId { get; set; }
}

我希望我的解释已经足够,如果我应该在这里添加任何其他信息让我知道。

标签: c#domain-driven-designcqrs

解决方案


通常,您不会将域模型中的实体用作命令的元素。

命令本质上是消息,因此它们确实应该是不可变的。您想知道收到的内容与发送的内容相同。在 DDD 术语中,您可能将消息视为值对象

使用域模型中的实体作为命令的内存表示的一部分是没有意义的,因为您永远不应该调用任何改变其状态的实体方法。

与域模型实体相比,命令在本质上更接近于数据传输对象。

通常,系统中的所有实体对象都应该存在于聚合根接口之后,并且传递给该接口的参数是values。如果域模型需要一个实体,它可以根据提供的值创建一个。


推荐阅读