C# res很容易查询,这就是为什么在持久性级别需要一种形式的持久性查询。顺便说一句,存储库不仅有CRUD职责。-1您将概念弄得一团糟。命令处理程序不应该访问读取模型,因为读取模型不是它所关心的,并且读取模型可以异步生成,因此处理程序将处理不一致的模型。聚合根不

C# res很容易查询,这就是为什么在持久性级别需要一种形式的持久性查询。顺便说一句,存储库不仅有CRUD职责。-1您将概念弄得一团糟。命令处理程序不应该访问读取模型,因为读取模型不是它所关心的,并且读取模型可以异步生成,因此处理程序将处理不一致的模型。聚合根不,c#,cqrs,event-sourcing,C#,Cqrs,Event Sourcing,res很容易查询,这就是为什么在持久性级别需要一种形式的持久性查询。顺便说一句,存储库不仅有CRUD职责。-1您将概念弄得一团糟。命令处理程序不应该访问读取模型,因为读取模型不是它所关心的,并且读取模型可以异步生成,因此处理程序将处理不一致的模型。聚合根不查询任何内容,存储库查询。ES意味着将对象状态表示为事件流,这是一个实现细节,在定义存储库的接口时没有任何发言权。最后,您将UI/报表查询与域查询混淆,这是另一回事。既然您非常确定,请在中向我展示一个带有查询的存储库。问题是关于CQRS+ES。


res很容易查询,这就是为什么在持久性级别需要一种形式的持久性查询。顺便说一句,存储库不仅有CRUD职责。-1您将概念弄得一团糟。命令处理程序不应该访问读取模型,因为读取模型不是它所关心的,并且读取模型可以异步生成,因此处理程序将处理不一致的模型。聚合根不查询任何内容,存储库查询。ES意味着将对象状态表示为事件流,这是一个实现细节,在定义存储库的接口时没有任何发言权。最后,您将UI/报表查询与域查询混淆,这是另一回事。既然您非常确定,请在中向我展示一个带有查询的存储库。问题是关于CQRS+ES。如果这直接出现在问题中,那么我们现在如何从实现细节中抽象出来呢???在一个事件源写模型中,不可能有任何查询,这是一个明确的说法。我同意从命令处理程序进行查询。这是我的错误,我相应地改变了答案。但我真的很感谢Greg Young或Eric Evans对术语“域查询”的任何引用,提前谢谢你。你知道你指的是一个简单的例子,不需要更多的“获取”吗?所有的领域和需求都相同吗?不。对于许多开发人员来说,ES和CQR同时存在,这是一个CQR问题,也是一个设计问题。存储库接口从不关心您使用的是ES或其他什么。实现(域)用例的服务使用一个或多个DDD repo。在某些情况下,您需要根据存储库中的条件获取所有相关聚合。这是您的域查询。请随意为它想出一个更好的术语。一个由格雷格·Y.或埃里克·E·迈克批准的,我已经读了你在另一个问题中提到的帖子。我完全同意关于域与数据模型分离的说法,许多与EF相关的DDD教程将它们紧密地结合在一起,这是不好的。然而,你的许多陈述是一个长期的讨论主题,没有黑白之分。存储库模式是最主观的话题之一。您的愿景更符合Fowler的存储库,它与DDD几乎没有关系。这是我在这篇讨论中的最后一篇文章。问题是票务量可能会根据其状态或类别而变化。这意味着每次用户想要更新tixket时,我都必须更新2个聚合,这违反了DDDb的原则/指南,但是用户不能加载其分配的票证并计算实际负载吗?我的猜测是票证负载在不同的时间点发生变化。这是一个解决方案,但我还没有做出决定:聚合是否应该访问存储库?我认为没有任何模式应该限制我们做正确的事情,或者鼓励我们做相反的事。我认为访问存储库的聚合没有任何错误,只要它作为依赖项传递,并且没有更新。当然,您可以将存储库包装到服务中。这样就没有可保存到的存储库,而且更容易强制执行不更新。
public void AssignTicketToUser(int teamId, int ticketId)
{
    var ticket = repository.Get<Ticket>(ticketId);
    var team = repository.Get<Team>(teamId);
    var users = new UserLocator(repository);
    var tickets = new TicketLocator(repository);
    var user = team.GetUserWithLowestLoad(users, tickets);

    user.AssignTicket(ticket);

    repository.Save(user);
}
public User GetGetUserWithLowestLoad(ILocateUsers users, ILocateTickets tickets)
{
    User lowest = null;

    foreach(var id in userIds)
    {
        var user = users.GetById(id);
        if(user.IsLoadedLowerThan(lowest, tickets))
        {
            lowest = user;
        }
    }
    return lowest;
}
public bool IsLoadedLowerThan(User other, ILocateTickets tickets)
{
    var load = CalculateLoad(tickets);
    var otherLoad = other.CalculateLoad(tickets);

    return load < otherLoad;
}

public int CalculateLoad(ILocateTickets tickets)
{
    return assignedTicketIds
        .Select(id => tickets.GetById(id))
        .Sum(ticket.CalculateLoad());
}
public void AssignTicket(Ticket ticket)
{
    if(ticketIds.Contains(ticket.Id)) return;

    Publish(new TicketAssignedToUser
        {
            UserId = id,
            Ticket = new TicketLoad
                {
                    Id = ticket.Id,
                    Load = ticket.CalculateLoad() 
                }
        });
}

public void When(TicketAssignedToUser e)
{
    ticketIds.Add(e.Ticket.Id);
    totalLoad += e.Ticket.Load;
}