在现代软件开发中,命令查询责任分离(CQRS)是一种设计模式,它将应用程序的读操作和写操作分离开来,以提高性能和可伸缩性。本文将介绍一个基于“超级简单的CQRS”示例的库存管理应用的实现。目前,该应用只实现了创建库存项的第一个用例。
库存管理应用的代码存放在GitHub仓库中,可以通过提供的链接访问。请注意,本文是系列文章的一部分,所有相关文章的链接将在文章末尾提供。
在构建大型企业级应用时,服务总线框架和解耦消息机制是至关重要的。它们允许系统的不同部分通过消息传递进行通信,而不需要直接调用对方的接口。这种模式提高了系统的灵活性和可维护性。
在CQRS架构中,命令是用于修改系统状态的操作。在库存管理应用中,创建库存项就是一个命令。当用户提交创建库存项的请求时,系统会生成一个命令对象,并将其发送到命令处理器。
聚合是CQRS中用于表示实体的一组相关对象的集合。在库存管理应用中,库存项就是一个聚合。每个聚合都有一个唯一的标识符,并且可以响应命令来更新其状态。事件源是一种模式,它记录了聚合状态的所有变化,以便可以重构历史状态或用于其他目的。
在CQRS架构中,读取侧负责提供系统的查询功能。在库存管理应用中,读取侧使用一个视图模型生成器来处理事件,并在数据库中创建新的库存项。这个数据库是一个基于Code-first EF SQL数据库的读取侧数据库。
在库存管理应用的读取侧,视图模型生成器处理名为InventoryCreated
的事件。这个处理器与读取模型一起工作,并在读取侧的数据库中创建一个新的库存项并保存。
网站从读取数据库中读取数据,使用一个薄的数据访问层,并在MVC视图中显示它。在读取侧的数据访问层中,一个有趣的点是Func<>
的使用。
在读取侧的薄数据层中,Func<>
被用来处理依赖注入。例如,在HomeController
中,它调用InventoryItemsDao
来检索所有库存项的列表。在C#中,这可以通过以下代码实现:
public class HomeController : Controller {
private readonly IServiceBus _bus;
private readonly InventoryItemsDao _inventoryItemsDao;
public HomeController() {
_bus = IoC.Resolve<IServiceBus>();
_inventoryItemsDao = IoC.Resolve<InventoryItemsDao>();
}
public ActionResult Index() {
var inventoryItems = _inventoryItemsDao.GetAllInventoryItems();
return View(inventoryItems);
}
// .. Code
}
在这种情况下,没有为InventoryItemsDao
在IOC容器中进行注册。因此,IOC会尝试创建该类的实例,并解决其构造函数中提供的任何依赖项。