简体   繁体   English

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

[英]Why RowVersion property is not raising optimistic concurrency exception when two concurrent changes occur?

I have the following entity, 我有以下实体,

 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; }

    }

and the BaseEntity is, 而BaseEntity是,

 public class BaseEntity : ISoftDelete {
        public bool IsDeleted { get; set; }

        [Timestamp]
        public byte[] RowVersion { get; set; }
    }

the entity has RowVersion property and I use the fluent API to configure it as RowVersion. 该实体具有RowVersion属性,我使用流畅的API将其配置为RowVersion。 I use the repository pattern and this is how I load the entity in the context, 我使用存储库模式,这就是我在上下文中加载实体的方式,

 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);
        }

and in my controller, I update as following, 在我的控制器中,我更新如下,

[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);
}

Now if I access the same record with two different users and one of the alters AliasName and saves the second user that accessed the record will still be able to save new changes without I get a concurrency exception. 现在,如果我用两个不同的用户访问其中一个记录,并且其中一个alters AliasName并保存了另一个访问记录的用户,那么在没有发生并发异常的情况下,仍然可以保存新的更改。 why are the concurrent updates here not raising an update exception? 为什么这里的并发更新没有引发更新异常?

this is the Fluent API config, 这是Fluent API配置,

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

I have the update log here 我在这里有更新日志

UPDATE 更新

For future reference, 备查,

Based on the docs here , we can test for concurrency conflict by just manipulating one of the values before calling save. 根据此处的文档,我们可以通过在调用save之前操作一个值来测试并发冲突。

ie

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

this will raise up an exception. 这将引发一个例外。

If the read from second user is after the write from first user then the second user's RowVersion will reflect the value at the time (ie after the first update). 如果从第二个用户读取是第一个用户写入之后 ,则第二个用户的RowVersion将反映当时的值(即第一次更新之后)。 Thus - no concurrency issue. 因此-没有并发问题。

You will only get an issue if they both read (and thus get the same RowVersion ) and then both try and write. 如果它们都读取(并因此获得相同的RowVersion ), 然后都尝试写入, 只会出现问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM