代码之家  ›  专栏  ›  技术社区  ›  JSON

为什么当发生两个并发更改时,RowVersion属性不引发乐观并发异常?

  •  1
  • JSON  · 技术社区  · 7 年前

    我有以下实体,

     public class PatientRegistry : BaseEntity {
    
            [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
            [Display(Name = "Patient File Number")]
            public long PatientFileId { get; set; }
            public virtual ICollection<PartnerRegistry> Partners { get; set; }
            public string UserId { get; set; }
            public string AliasName { get; set; }
    
            public DateTime? DateNow { get; set; }
            public virtual ApplicationUser User { get; set; }
    
        }
    

    基本实体是,

     public class BaseEntity : ISoftDelete {
            public bool IsDeleted { get; set; }
    
            [Timestamp]
            public byte[] RowVersion { get; set; }
        }
    

    RowVersion 属性和我使用fluent API将其配置为RowVersion。我使用存储库模式,这就是我在上下文中加载实体的方式,

     public async Task<PatientRegistry> GetPatient(long Id, bool isPartners = true, bool isUser = true) {
                if (isPartners && !isUser)
                  return await context.PatientsRegistry
                    .IgnoreQueryFilters()
                    .Include(pt => pt.Partners)
                    .Include(pt => pt.User)
                    .Include(pt => pt.User.Gender)
                    .Include(pt => pt.User.Nationality)
                    .Include(pt => pt.User.Occupation)
                    .Include(pt => pt.User.Ethnicity)
                    .Include(pt => pt.User.MaritalStatus)
                    .Include(pt => pt.User.Country)
                    .Include(pt => pt.User.State)
                    .Include(pt => pt.User.City)
                    .Include(pt => pt.User.Database)
                    .Include(pt => pt.User.UserAvatar)
                    .SingleOrDefaultAsync(pt => pt.PatientFileId == Id);
            }
    

    [HttpPut("{FileId}")]
    public async Task<IActionResult> UpdatePatient([FromRoute] PatientFileIdResource fileIdModel, [FromBody] SavePatientsRegistryResource model)
    {
        ApiSuccessResponder<PatientRegistryResource> response = new ApiSuccessResponder<PatientRegistryResource>();
        if (!ModelState.IsValid)
            return BadRequest(ModelState);
        Task<PatientRegistry> getPatientTask = repository.GetPatient(fileIdModel.FileId.Value);
        Task<RequestHeaderResource> getHeaderRequestTask = headerRequestService.GetUserHeaderData();
        await Task.WhenAll(getPatientTask, getHeaderRequestTask);
        PatientRegistry patient = await getPatientTask.ConfigureAwait(false);
        RequestHeaderResource header = await getHeaderRequestTask.ConfigureAwait(false);
        if (patient == null)
        {
            ModelState.AddModelError(string.Empty, "The patient does not exist in the database");
            return BadRequest(ModelState);
        }
    
        patient.DateNow = DateTime.Now;
        patient.AliasName = model.AliasName;
        await unitOfWork.CompleteAsync(header);
        return StatusCode(200, response);
    }
    

    现在,如果我用两个不同的用户访问同一个记录,并更改其中一个 AliasName 保存第二个访问记录的用户仍然可以保存新的更改,而不会出现并发异常。为什么这里的并发更新不会引发更新异常?

    这是Fluent API配置,

     builder.Entity<PatientRegistry>()
            .Property(a => a.RowVersion).IsRowVersion()
            .IsConcurrencyToken()
            .ValueGeneratedOnAddOrUpdate();
    

    我有更新日志 here

    更新

    根据文件 here ,我们可以通过在调用save之前操作其中一个值来测试并发冲突。

    context.Database.ExecuteSqlCommand("UPDATE dbo.PatientsRegistry SET AliasName = 'Jane' WHERE PatientFileId = 2222");
    await context.SaveChangesAsync();
    

    这将引起一个例外。

    1 回复  |  直到 7 年前
        1
  •  4
  •   mjwills Myles McDonnell    7 年前

    如果从第二个用户读取的 第一个用户的写操作,然后第二个用户的 RowVersion 之后 第一次更新)。因此-没有并发问题。

    只有当他们都读到了,你才会有问题 行版本 )以及 然后