CQRS DDD - 命令和域模型关系

CQRS DDD - Commands and Domain Models relationship

我正在练习尽我所能使用 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 解决方案文件夹中。

驻留在 Domain 解决方案文件夹中的 Model 项目托管 BookShelf 实体 class,其中包括书籍集合。

问题 1: 上面的命令有这个 Books 属性 类型 Book。我的问题是:Commands 项目是否应该直接引用模型项目,以便 Book 数据类型在 CreateNewBookShelfCommand 中解析?我个人认为 Contracts 不允许引用除 CommandHandlers 以外的任何项目或任何其他可能 Cross Cutting 的项目。

问题 2: 那么,在 Contracts 项目中复制 Book 实体 class 的一部分是否是一个好习惯并在 CreateNewBookShelfCommand?

这是我为 BookBookShelf:

准备的模型项目
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; }
}

我希望我的解释已经足够了,如果有任何其他信息我应该在这里添加,请告诉我。

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

命令基本上是消息,因此它们确实应该是不可变的。你想知道收到的和发送的是一样的。在 DDD 术语中,您可能会将消息视为 值对象

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

命令在本质上更接近于数据传输对象,而不是域模型实体。

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