c# - 使用 CQRS 方法处理并发

标签 c# entity-framework concurrency architecture cqrs

我在我的架构中使用 CQRS 方法,例如,我有一个如下命令:

public class ModifyDepartmentInformationCommand
{
    public ModifyDepartmentInformationCommand() { }
    public ModifyDepartmentInformationCommand(int departmentId, string departmentName, byte[] version)
    {
        DepartmentId = departmentId;
        DepartmentName = departmentName;
        Version = version;
    }

    public int DepartmentId { get; set; }
    public string DepartmentName { get; set; }                 
    public byte[] Version { get; set; }        
}

它的处理程序看起来像:

 public class ModifyDepartmentInformationCommandHandler : 
    IRequestHandler<ModifyDepartmentInformationCommand, ModifyDepartmentInformationCommandResult>
 {
    private readonly IMgpCommandContext _mgpCommandContext;

    public ModifyDepartmentInformationCommandHandler(IMgpCommandContext mgpCommandContext)
    {
        _mgpCommandContext = mgpCommandContext;            
    }

    public ModifyDepartmentInformationCommandResult Execute(ModifyDepartmentInformationCommand request)
    {            
        new ModifyDepartmentInformationCommandValidator().ValidateAndThrow(request);
        var department = _mgpCommandContext.Departments.SingleOrDefault(o => o.Id == request.DepartmentId);
        if (department == null) { throw new ApplicationException("DepartmentDoesNotExist", "There is no such department."); }
        department.ModifyInformation(request.Version, request.DepartmentName);
        _mgpCommandContext.SaveChanges();
        return new ModifyDepartmentInformationCommandResult();                                                           
    }
}

如您所见,Version 用作并发 token 。它与命令一起传递,并在命令处理程序中传递给部门的域实体操作ModifyInformation,它设置版本:

public class Department
{
    ...

    public void ModifyInformation(byte[] version, string departmentName)
    {
        Version = version;
        Name = departmentName;

        new DepartmentValidator().ValidateAndThrow(this);
    } 
}

因为 Department 域实体上的 Version 属性是使用 EF Code First 映射的,如下所示:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
 {
      modelBuilder.Entity<Department>().ToTable("Department").Property(p => p.Version).IsRowVersion().IsConcurrencyToken(); ;          
 }

...从在上下文上执行 SaveChanges 的那一刻起,就会正确检测到并发性。

这就是现在的工作方式...我的问题与我在部门级别有一个并发 token 这一事实有关。因此,如果我有每个修改部门不同属性的命令,则使用相同的并发 token 。

因此,如果两个用户查询部门X,用户1使用一条命令更改部门名称,用户2使用另一条命令更改部门的某些其他属性;那么提交该命令的第二个用户仍然可能会遇到并发冲突,即使它不是被修改的属性。

这是正确的方法,还是有更好的方法来处理命令中的并发性,例如对实体使用多个并发 token ?一般采取什么方法?

最佳答案

您选择了正确的方法。另外,您可以将部门配置拆分为多个逻辑部分,例如:公共(public)参数、安全性等。每个部分都将被单独考虑,并且每个部分都有自己的版本。

关于c# - 使用 CQRS 方法处理并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25451610/

相关文章:

c# - uwp 标题栏中的后退按钮不可见

c# - 从 iframe 重定向到页面

sql-server - 使用序列作为 Entity Framework 中主键值的生成器插入

java - 为什么CopyOnWriteArrayList中没有这样的removeRange()方法?

c++11 - 如果两个原子的 fetch_add 同时执行会发生什么?

c# - 用递归求解有向图

c# - 使用静态变量来存储全局的、不断变化的信息是一种好习惯吗?

c# - 打破 POCO 关系

c# - 只返回计数大于 X 的对象

java - 线程优先级没有影响