【发布时间】:2019-09-22 04:28:44
【问题描述】:
我在我的系统中使用命令查询分离。
为了描述问题,让我们从一个例子开始。假设我们有如下代码:
public class TenancyController : ControllerBase{
public async Task<ActionResult> CreateTenancy(CreateTenancyRto rto){
// 1. Run Blah1Command
// 2. Run Blah2Command
// 3. Run Bar1Query
// 4. Run Blah3Command
// 5. Run Bar2Query
// ...
// n. Run BlahNCommand
// n+1. Run BarNQuery
//example how to run a command in the system:
var command = new UploadTemplatePackageCommand
{
Comment = package.Comment,
Data = Request.Body,
TemplatePackageId = id
};
await _commandDispatcher.DispatchAsync(command);
return Ok();
}
}
CreateTenancy 的实现非常复杂,可以运行许多不同的查询和命令。
每个命令或查询都可以在系统的其他地方重复使用。
每个命令都有一个 CommandHandler
每个查询都有一个 QueryHandler
例子:
public class UploadTemplatePackageCommandHandler : PermissionedCommandHandler<UploadTemplatePackageCommand>
{
//ctor
protected override Task<IEnumerable<PermissionDemand>> GetPermissionDemandsAsync(UploadTemplatePackageCommand command) {
//return list of demands
}
protected override async Task HandleCommandAsync(UploadTemplatePackageCommand command)
{
//some business logic
}
}
每次您尝试运行命令或查询时,都会进行权限检查。 CreateTenancy 中出现的问题是当您运行 10 个命令时。
有时您对前 9 个命令都具有权限,但缺少一些运行最后一个命令的权限。在这种情况下,您可以对运行这 9 个命令的系统进行一些复杂的修改,最后,您无法完成整个事务,因为您无法运行最后一个命令。在这种情况下,需要进行复杂的回滚。
我相信在上面的例子中,权限检查应该只在整个事务开始时进行一次,但我不确定实现这一点的最佳方法是什么。
我的第一个想法是创建一个名为让我们说CreateTenancyCommand 的命令,并在HandleCommandAsync 中放置CreateTenancy(CreateTenancyRto rto) 的整个逻辑
所以它看起来像:
public class CreateTenancyCommand : PermissionedCommandHandler<UploadTemplatePackageCommand>
{
//ctor
protected override Task<IEnumerable<PermissionDemand>> GetPermissionDemandsAsync(UploadTemplatePackageCommand command) {
//return list of demands
}
protected override async Task HandleCommandAsync(UploadTemplatePackageCommand command)
{
// 1. Run Blah1Command
// 2. Run Blah2Command
// 3. Run Bar1Query
// 4. Run Blah3Command
// 5. Run Bar2Query
// ...
// n. Run BlahNCommand
// n+1. Run BarNQuery
}
}
我不确定在另一个命令的命令处理程序中调用命令是否是一种好方法? 我认为每个命令处理程序应该是独立的。
权限检查应该只发生一次,我说得对吗? 如果是 - 在您想运行命令修改数据库然后将一些数据返回给客户端的情况下如何进行权限检查? 在这种情况下,您需要进行 2 次权限检查... 当您修改运行命令的数据库然后由于缺少某些权限而无法运行仅读取数据库的查询时,可能存在理论上的情况。如果系统很大并且有数百个 不同的权限,甚至良好的单元测试覆盖率都可能失败。
我的第二个想法是在命令和查询之上创建某种包装器或额外层,并在那里进行权限检查 但不知道如何实现。
在上面示例中控制器的操作中实现的所描述事务CreateTenancy 中进行权限检查的正确方法是什么?
【问题讨论】:
标签: c# asp.net-mvc domain-driven-design cqrs