首页 > 解决方案 > DDD 逻辑中的批量操作

问题描述

我目前正在探索 DDD 并且已经阅读了很多关于该主题的内容,但是当我正在处理更复杂的场景时,我正在考虑解决批量操作的概念问题的正确方法。

我还使用 CQRS(不应该包含嵌套命令)方法来解决我的问题(以及从技术角度来看的 MediatR)。

当前状态

想象一下,我有以下 ShoppingController,它有 3 个端点(CreateShoppingList、AddItemToShoppingList、UpdateItemOnShoppingList),每个端点只创建一个在命令处理程序中处理的命令。

ShoppingController.cs

...
public class ShoppingController {
    ....
    
    [HttpPost]
    Task CreateShoppingList() {
        ...
        _mediatR.Send(new CreateShoppingListCommand(...))
    }

    [HttpPost]
    Task AddItemToShoppingList() {
        ...
        _mediatR.Send(new AddItemToShoppingListCommand(...))
    }

    [HttpPut]
    Task UpdateItemOnShoppingList() {
       ...
        _mediatR.Send(new UpdateItemOnShoppingListCommand(...))
    }
}

ShoppingListCommandHandler处理 CQRS 命令:它使用一些业务逻辑(从存储库获取,调用聚合上的东西)并最后保存更改。

ShoppingListCommandHandler.cs

...
public class ShoppingListCommandHandler : 
ICommandHandler<CreateShoppingListCommand>,
ICommandHandler<AddItemToShoppingListCommand>,
ICommandHandler<UpdateItemOnShoppingListCommand> {
    ....
    
    Task Handle(CreateShoppingListCommand command) {
        // Business Logic A
        _shoppingListRepository.SaveChanges();      
    }

    Task Handle(AddItemToShoppingListCommand command) {
        // Business Logic B including _shoppingListRepository.Get() to retrieve the list        _shoppingListRepository.SaveChanges();      
    }

    Task Handle(UpdateItemOnShoppingListCommand command) {
        // Business Logic C including _shoppingListRepository.Get() to retrieve the list
        _shoppingListRepository.SaveChanges();      
    }
}

问题

当用作原子单元时,这些操作绝对没问题。但我知道想要创建一个从文件中导入这些东西的过程。流程如下: 检查用户是否有购物清单。如果他这样做了,请将这些项目添加到列表中,如果它们不存在的话;或更新数量(如果已经存在)。如果他没有创建列表,然后继续上面的操作。

显然,最好有某种形式的验证,无论用户是否存在(因为我可能在我的文件中犯了一个错误)。

所以我接近它如下:

  1. 读取文件并准备命令,其中唯一的字段是我获得的行
  2. 部署和处理命令

用于此的命令处理程序如下所示:

...
public class ShoppingListCommandHandler : 
ICommandHandler<CreateShoppingListCommand>,
ICommandHandler<AddItemToShoppingListCommand>,
ICommandHandler<UpdateItemOnShoppingListCommand>,
ICommandHandler<ImportShoppingListCommand>
 {
    ....
    
    Task Handle(CreateShoppingListCommand command) {
        // Business Logic A
        _shoppingListRepository.SaveChanges();      
    }

    Task Handle(AddItemToShoppingListCommand command) {
        // Business Logic B including _shoppingListRepository.Get()
        _shoppingListRepository.SaveChanges();      
    }

    Task Handle(UpdateItemOnShoppingListCommand command) {
        // Business Logic C including _shoppingListRepository.Get()
        _shoppingListRepository.SaveChanges();      
    }

    Task Handle(ImportShoppingListCommand command) {

        //Validate File
        ...
        // Retrieve all the required things that will be needed in subsequent processing to avoid
making additional DB calls
        ...
        // Custom Business Logic D1 to update existing lists and add/update items
        // Custom Business Logic D2 to create new lists and add/update items
        ....
        _shoppingListRepository.Update(D1);
        _shoppingListRepository.Add(D2);      
    }

}

如您所见,导入的逻辑是自定义编写的,并针对性能进行了优化。但是,我的文件可能包含重复项(默认情况下不会使文件无效,但例如同一购物清单的两行),将来,业务逻辑 A、B 和 C 可以包含更多验证(例如调用 shoppingListRepository 来检查每个家庭只有一个购物清单)。

有什么方法可以使这个调用高效(不是每个操作对 DB 的 X 次调用或为要存储的每一行创建 10 个命令),并确保逻辑没有完全重复,并且我只需要更新一件事?

标签: c#domain-driven-design

解决方案


推荐阅读