我正在尝试用cqrs了解事件来源。据我所知 - 命令处理程序保存对关系数据库的更改并抛出应该保存在nosql数据库中的事件。我有Notes类(这是我在数据库中的表):
public partial class Notes
{
public System.Guid Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public System.DateTime CreatedDate { get; set; }
public System.DateTime ModifiedDate { get; set; }
}
如果某人仅修改单个音符的标题,那么我应该创建具有属性的事件:Id和Title,或者可能包含类Notes的所有属性?因为现在我创建了包含所有属性的事件 - 我不会检查哪个属性已更改:
public abstract class DomainEvent
{
public Guid Id { get; set; }
public DateTime CreatedDateEvent { get; set; }
}
// my event:
public class NoteChangedEvent : DomainEvent
{
public string Title { get; set; }
public string Content { get; set; }
public DateTime ModifiedDate { get; set; }
}
// my command handler class:
public class EditNoteCommandHandler : ICommandHandler<EditNoteCommand>
{
private readonly DbContext _context;
private readonly IEventDispatcher _eventDispatcher;
public EditNoteCommandHandler(DbContext context, IEventDispatcher eventDispatcher)
{
_context = context;
_eventDispatcher = eventDispatcher;
}
public void Execute(EditNoteCommand command)
{
Notes note = _context.Notes.Find(command.Id);
note.Title = command.Title;
note.Content = command.Content;
note.ModifiedDate = DateTime.Now;
_context.SaveChanges(); // save to relational database
// throw event:
NoteChangedEvent noteChangedEvent = new NoteChangedEvent
{
Id = note.Id,
Title = note.Title,
Content = note.Content,
ModifiedDate = note.ModifiedDate,
CreatedDateEvent = DateTime.Now
};
_eventDispatcher.Dispatch(noteChangedEvent);
}
}
// my dispatcher class:
public class EventDispatcher : IEventDispatcher
{
public void Dispatch<TEvent>(TEvent @event) where TEvent : DomainEvent
{
foreach (IEventHandler<TEvent> handler in DependencyResolver.Current.GetServices<IEventHandler<TEvent>>())
{
handler.Handle(@event);
}
}
}
我这样做是否正确并且理解是否正确?
答案 0 :(得分:1)
我正在尝试用cqrs来理解事件采购。
据我所知 - 命令处理程序保存对关系数据库的更改并抛出应保存在nosql数据库中的事件。
没有。想想在不同时间发生的两种不同行为。
首先:命令处理程序保存事件(通常会有多个事件)。这是事件采购部分 - 事件的顺序是记录系统;事件用于为下一个 write 重新实现实体,因此事件存储是CQRS的 C 方面的一部分。
为此部分使用nosql数据库是一个实现细节;使用关系数据库来存储事件是相当常见的(例如:http://blog.oasisdigital.com/2015/cqrs-linear-event-store/)。
在完成对记录系统的写入之后,该数据(事件流)用于在读取模型中创建新投影。这可以有你喜欢的任何表示,但理想情况下,最适合你的阅读模型。换句话说,您可以在关系数据库中创建数据的表示形式;或者你可以运行一堆查询并将结果缓存在一个nosql商店中,或者.... CQRS的目的是将写入问题与读取问题分开 - 一旦你完成了,你可以单独调整每一方面
请注意,如果您从一个正在从对象存储库读取和写入的写入模型开始,将该模型扩展到调度事件(正如您在此处所做的那样)是一个合理的中间步骤。
但是如果你从头开始,你就不会在写模型中保存Note的当前状态(没有对象存储),只是将音符置于当前状态的事件序列。
如果有人只修改单个标题的标题,那么我应该创建具有属性的事件:Id和Title,或者可能包含类Notes的所有属性?
最佳做法是描述变化。
通常使用更细粒度的事件来完成。您可以使用EntityChanged,枚举已更改的字段(在大多数情况下,包括实体ID)。在CRUD解决方案中,有时候这一切都是有意义的。
但是,如果您正在为业务领域建模,通常会有一些上下文 - 这些变化的动机。完全充实的事件模型可能有多个事件描述对同一组字段的更改(考虑更正客户的邮件地址与跟踪客户已重新定位的用例)。
关键是如果写模型可以描述更改背后的含义,那么读模型不需要尝试从事件中包含的通用数据中猜测它。
发现该意图通常意味着在命令中捕获更多语义信息(在将其发送到写入模型之前)。换句话说,EditNoteCommand本身是模糊的,并且可以重命名事件以更明确地表达感兴趣的不同类型的编辑。