gpt4 book ai didi

c# - 事件溯源——我们应该只将对象或所有对象值的变化保存到事件存储中吗?

转载 作者:行者123 更新时间:2023-11-30 17:39:23 25 4
gpt4 key购买 nike

我正在尝试使用 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 和标题,或者可能具有笔记类的所有属性?因为现在我使用所有属性创建事件 - 我不检查哪个属性已更改:

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

我这样做是否正确,我的理解是否正确?

最佳答案

I am trying to understand event sourcing with cqrs.

As I understand - command handler saves changes to relational database and throws event which should be save in nosql database.

没有。想一想在不同时间发生的两种不同的行为。

首先:命令处理程序保存事件(通常会有多个)。那是事件溯源部分——事件的顺序是记录系统;事件用于为下一次写入补充实体,因此事件存储是 CQRS C 端的一部分。

这部分使用nosql数据库是一个实现细节;使用关系数据库存储事件相当普遍(例如:http://blog.oasisdigital.com/2015/cqrs-linear-event-store/)。

写入记录系统完成后,该数据(事件流)用于在读取模型中创建新投影。这可以是您喜欢的任何表示,但理想情况下是最适合您的阅读模型的任何表示。换句话说,您可以在关系数据库中创建数据表示;或者你可以运行一堆查询并将结果缓存在 nosql 存储中,或者...... .

请注意,如果您从一个写入模型开始,您正在从对象存储中读取和写入,那么扩展该模型以分派(dispatch)事件(正如您在此处所做的那样)是一个合理的中间步骤。

但如果您从头开始,您将永远不会在写入模型(无对象存储)中保存笔记的当前状态,而只会保存将笔记带到当前状态的事件序列。

If somebody modify only Title of a single note then I should create event with properties: Id and Title or maybe with all properties of class Notes?

最佳做法是描述更改。

这通常通过更细粒度的事件来完成。您可以摆脱 EntityChanged,枚举已更改的字段(在大多数情况下,包括实体 ID)。在 CRUD 解决方案中,有时这就是有意义的。

但是如果您正在为业务领域建模,通常会有一些背景 - 一些改变的动机。一个完全充实的事件模型可能有多个事件描述对同一组字段的更改(考虑更正客户邮寄地址与跟踪客户搬迁的用例)。

关键在于,如果写入模型可以描述更改背后的含义,则读取模型无需尝试从事件中包含的通用数据中进行猜测。

发现该意图通常意味着在命令中捕获更多语义信息(在将其发送到写入模型之前)。换句话说,EditNoteCommand 本身是模糊的,并且可以重命名事件以更明确地表达感兴趣的不同类型的编辑。

关于c# - 事件溯源——我们应该只将对象或所有对象值的变化保存到事件存储中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35608919/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com