标签: cqrs

如何限制CQRS中的查询类数?

我正在实施CQRS,我对查询的查询速度有多困惑.我也搜索了它,但由于CQRS的各种风味,我没有得到任何适当的解决方案.也许我在这里做错了什么?这是我的代码和各自的查询.

class User {
   public int Id { get; set; }   
   public string Username { get; set; }
   public string Status { get; set; }
   public string Role { get; set; }
   // ...
}
Run Code Online (Sandbox Code Playgroud)

我想通过用户名找到用户,所以我已经为它编写了查询

abstract class Query<TResult> { }
class FindUserByStatusQuery : Query<IEnumerable<User>> {
       public string Status;
}
Run Code Online (Sandbox Code Playgroud)

以及它的相应处理程序

interface IQueryHandler<TQuery, TResult> where TQuery : Query<TResult>
{ 
    TResult Handle(TQuery query);     
} 

class FindUserByStatusQueryHandler : IQueryHandler<FindUserByStatusQuery, IEnumerable<User>> 
{
               public IEnumerable<User> Handle(FindUsersByAcountStatusQuery query)
               {   
                   using (Entities db = new Entities()) …
Run Code Online (Sandbox Code Playgroud)

c# entity-framework cqrs

2
推荐指数
1
解决办法
644
查看次数

CQRS /事件来源:如何实施数据完整性?

如果我实现CQRS和事件源,那么假设数据的最终存储(读取存储)在RDBMS中,那么如何保持数据的完整性和一致性?

如果发布事件但由于违反检查或缺少FK引用而RDBMS拒绝从该事件派生的数据怎么办?

cqrs event-sourcing

2
推荐指数
1
解决办法
882
查看次数

域驱动设计 - 跨不同聚合的命令的复杂验证

我只是从DDD开始,目前正试图掌握用它做不同事情的方法.我正在尝试使用CQRS使用异步事件(没有事件源)来设计它.目前我坚持使用命令验证.我已经读过这个问题:在域驱动设计中进行验证,但是,没有一个答案似乎涵盖了不同聚合根的复杂验证.


假设我有这些聚合根:

  • 客户端 - 包含已启用服务的列表,每个服务都可以具有折扣的价值对象列表及其有效性.
  • DiscountOrder - 在给定客户的某些服务上实现更多折扣的订单,包含具有折扣配置的订单商品.
  • BillCycle - 生成账单的每个期间都由自己的账单周期描述.

这是用例:

可以提交折扣订单.折扣顺序中的每个新折扣期不应与任何BillCycles重叠.在一项服务上,不能同时激活两种相同类型的折扣.

基本上,在CRUD风格中使用Hibernate,这看起来类似于(java代码,但问题与语言无关):

public class DiscountProcessor {
    ...
    @Transactional
    public void processOrder(long orderId) {
        DiscOrder order = orderDao.get(orderId);
        BillCycle[] cycles = billCycleDao.getAll();

        for (OrderItem item : order.getItems()) {
            //Validate billcycle overlapping
            for (BillCycle cycle : cycles) {            
                if (periodsOverlap(cycle.getPeriod(), item.getPeriod())) {
                    throw new PeriodsOverlapWithBillCycle(...);
                }
            }
            //Validate discount overlapping
            for (Discount d : item.getForService().getDiscounts()) {
                if (d.getType() == item.getType() && periodsOverlap(d.getPeriod(), item.getPeriod())) {
                    throw new PeriodsOverlapWithOtherItems(...);
                } …
Run Code Online (Sandbox Code Playgroud)

language-agnostic validation domain-driven-design cqrs

2
推荐指数
1
解决办法
943
查看次数

遗留系统的CQRS

我是CQRS的初学者并且有一些问题.

背景是我们拥有20世纪80年代的遗留系统.我们希望实现一个瘦框架,供与之通信的新应用程序使用.

我们的想法是使用CQRS来实现这个框架,但我的问题是我们应该如何做到这一点.数据库和底层结构不会改变.

问题是系统和与它的通信非常慢.使用的协议是Telnet,FTP和一些自定义协议.

  1. 我们在实施时应该怎么想?
  2. (也许还有其他技术比CQRS更适合这个?)

c# legacy domain-driven-design legacy-database cqrs

2
推荐指数
1
解决办法
197
查看次数

我应该更新每个事件的阅读模型

Customer读过需要更新的模型NewOrderEvent.

有一件事我想理解,我应该在每个事件上更新我的阅读模型.或者我需要重播所有事件并替换读取模型.

我现在正在做的是:

  1. 保存 NewOrderEvent
  2. 获取或创建Customer阅读模型
  3. 调用Customer.ApplyEvent(NewOrderEvent)该更改Customer状态.
  4. 保存Customer读取模型

我错过了什么吗?

cqrs event-sourcing

2
推荐指数
1
解决办法
1120
查看次数

使用事件源时,使用聚合版本号是幂等的

使用DDD,CQRS和事件源时,可能会重新发送消息或无序发送消息.

我不太关心命令消息,因为用户会立即知道它是否成功.我关心的是事件.如果将聚合版本号附加到事件中,我们是否可以使操作具有幂等性?例如:

class Person {
    public function apply(PersonNameUpdated event) {
        if (version_ + 1 != event.version) {
            name_ = event.name;
            ++version_;
        }
    }
    private String name_;
    private Integer version_;
}
Run Code Online (Sandbox Code Playgroud)

domain-driven-design idempotent cqrs event-sourcing

2
推荐指数
1
解决办法
973
查看次数

发布实体状态更改的最佳实践

我有以下型号:

public class Team {
    public Guid Id {get; set;}
    public string Name {get; set;}
    public string League {get; get;}
    public int Rating {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

在系统中创建新团队后,我将事件发布TeamCreated到服务总线:

{
    "MessageId": "33909eaf-56a1-4467-a01a-64b94f10490c"
    "MessageType": "TeamCreated",
    "CreationDate": "20-01-2016",
    "Payload":  {
        "Id": "11111www-56a1-4467-a01a-64b94f000111",
        "Name": "Toronto Maple Leafs",
        "League": "NHL NorthEast",
        "Rating": 100
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来,此条目已修改为以下内容:

{
    "MessageId": "33909eaf-56a1-4467-a01a-64b94f10490c"
    "MessageType": "TeamUpdated",
    "CreationDate": "20-01-2016",
    "Payload":  {
        "Id": "11111www-56a1-4467-a01a-64b94f000111",
        "Name": "Toronto Maple Leafs",
        "League": "NHL NorthEast",
        "Rating": 50
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,他更新的消息仍保留所有属性的值,而不仅仅是已更改的属性,即团队的等级.

我的模型,在真实系统中有超过50个属性,我不希望在每个属性更新时为它们创建单独的事件.特别是因为可能是在一次更新中更改了多个属性的情况.

在事件采购架构中是否存在针对此场景的已定义模式?

domain-driven-design cqrs event-sourcing

2
推荐指数
1
解决办法
153
查看次数

我应该在Web Api Core中测试CQRS处理程序还是整个请求输出

我创建Web API已有一段时间了,很高兴能够测试CQRS处理程序(由Mediatr管理)而无需接触任何类型的基础架构代码(控制器,requets等)。在执行控制器应该做的事情时非常薄:请求和响应之间的通信:

    [HttpGet("requests")]
    public async Task<IEnumerable<AbsenceRequest>> GetAbsenceRequests(GetAbsenceRequests.Query query)
    {
        return await _mediator.Send(query);
    }
Run Code Online (Sandbox Code Playgroud)

但是仍然存在我的Handlers测试无法涵盖的情况。这里有几个例子:

  1. 授权。我无法测试“错误”用户是否尝试访问特定操作,他收到拒绝访问错误。换句话说,我无法测试特定操作的授权属性。
  2. 错误处理。我可以检查我的处理程序在特定条件下是否抛出了特定异常,但是我无法控制基础结构(即异常中间件)如何处理该异常(即导致特定的HTTP错误)。

ASP.NET Core使请求输入响应输出集成测试非常容易(由于使用了TestServer),我可以在集成测试中介绍这两种情况。

让我困扰的问题是我应该通过发送请求并声明响应来保持Handlers测试还是测试动作。

我真的很喜欢Handler测试。它们很可爱,清晰而且易于编写。测试整个请求的功能要强大得多,但同时它却是一个相对较低级别的方法,因此杂乱无章,您必须处理http和json。

我发现此选择非常令人困惑,并且想知道推荐的方法是什么。

.net cqrs asp.net-web-api mediatr asp.net-core

2
推荐指数
1
解决办法
988
查看次数

如何处理DDD + CQRS +事件采购方法中的业务规则?

我试图找出如何使用CQRS/ES方法处理复杂域模型.让我们假设我们有例如Order域实体,它处理订单的状态和行为.它有一个Status属性,带有用于在状态之间切换的转换规则(实现状态模式或任何其他类型的状态机).据DDD原理,该逻辑应在Order类(表示订单模型)来实现本身,具有类似的方法approve(),cancel(),ship()等.

看看这种体系结构的不同 公共 示例,结果表明域实体和聚合根是相同的,它处理状态和行为,甚至是自己对事件的预测.这不违反SRP吗?

但我的问题更具体:如果我想处理新命令(并应用新事件),我应该从事件流(即从写模型和写入数据库)重建实体并调用其行为方法(将事件应用于状态)处理业务规则?或者只是处理命令和事件本身,而没有任何写模型实体?

伪代码说明:

class ApproveOrderHandler
{
    private EventStore eventStore

    // ...

    public void handle(ApproveOrder event)
    {
        Order order = this.eventStore.findById(event.getOrderId()); // getting order projection from event store
        order.approve(); // handling business logic
        this.eventStore.save(order.releaseEvents()); // save new events (OrderApproved)
    }
}

class Order extends AbstractAggregate
{
    private Uuid id;

    private DateTime takenAt;

    private OrderStatus status;

    // ...

    public void approve()
    {
        this.status.approve(); // business rules blah blah
        this.Apply(new …
Run Code Online (Sandbox Code Playgroud)

architecture domain-driven-design business-rules cqrs event-sourcing

2
推荐指数
1
解决办法
1002
查看次数

org.axonframework.eventsourcing.IncompatibleAggregateException(Axon框架:应用事件后聚合标识符必须为非null)

我尝试使用axon 配置cqrs事件源. SeatReseveCreateCommand工作正常.但SeatReserveUpadateCommand无法正常工作.

这是我的SeatReserve 聚合

@Aggregate
public class SeatReserve {
    @AggregateIdentifier
    private String id;
    private String seatid;
    private Date date;

    @SuppressWarnings("unused")
    private SeatReserve() {
    }

    @CommandHandler
    public SeatReserve(SeatReseveCreateCommand seatReseveCreateCommand) {
        apply(new SeatReseveCreateEvent(seatReseveCreateCommand.getMyid(), seatReseveCreateCommand.getSeatId(),
                seatReseveCreateCommand.getDate()));
    }

    @CommandHandler
    public SeatReserve(SeatReserveUpadateCommand upadateCommand) {
        apply(new SeatReserveUpadateEvent(id, upadateCommand.getSeatId()));
    }

    @EventSourcingHandler
    public void on(SeatReseveCreateEvent seatReseveCreateEvent) {
        this.id = seatReseveCreateEvent.getId();
        this.seatid = seatReseveCreateEvent.getSeatId();
        this.date = seatReseveCreateEvent.getDate();
    }

    @EventSourcingHandler
    public void on(SeatReserveChangeEvent upadateEvent) {
        seatid = upadateEvent.getSeatId();
    }

}
Run Code Online (Sandbox Code Playgroud)

这是我的控制器

@RestController …
Run Code Online (Sandbox Code Playgroud)

cqrs event-sourcing axon spring-boot microservices

2
推荐指数
1
解决办法
1239
查看次数