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