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/

相关文章:

java - 哪个线程将在两个线程中获得并发修改异常

java - AtomicInteger 增量未按预期运行

C# 执行、等待、读取命令的输出

c# - 当模型属性设置为新实例时更新 MVVM View

c# - 如何在 C# 中不使用 Edmx 的情况下使用 DbContext?

asp.net - Entity Framework -Where 子句

c# - 无法找到程序集 Entity Framework v 4.4.0.0

scala - 包含在 Scala Future 中的 JDBC 调用

c# - 数据传输对象和报告

c# - 为 Thread.Sleep(TimeSpan) 设置高值