正如尼尔所说,好的做法是让表服务处理与并发相关的东西。
当我们使用客户端库从表服务中获取实体时,库会将与实体关联的 ETag(存在于实体的服务响应中)存储在 EntityDescriptior 实例中(EntityDescriptor 是由库维护的对象,用于上下文中的每个实体实例)
当您提交更新实体的请求时,sdk 将准备 HTTP 请求,主体为序列化为 XML 的实体,请求的 ETag 标头为存储在实体对应的实体描述符中的 ETag 值。
当表服务接收到这个更新实体实例的请求时,它会检查请求中的 ETag 是否与表存储中当前与实体关联的 ETag 匹配(如果发生其他更新,则与存储在服务中的实体关联的 ETag 会更改)在收到您的更新请求之前),如果不匹配,则通过在 412 或 409 的响应中设置 Http 状态代码,服务返回前置条件失败/冲突错误。
bool done = true;
while (!done)
{
Stat statistics = _context.Execute<Stat>(new Uri("https://management.core.windows.net/<subscription-id>/services/storageservices/StatEntity?RowKey=..&PartitionKey=..").FirstOrDefault();
try
{
// TODO: Update the entity, e.g. statistics.ReadCount++
_context.UpdateObject(statistics);
_context.SaveChanges();
// success
break;
}
catch (DataServiceRequestException exception)
{
var response = exception.Response.FirstOrDefault();
if (response != null && (response.StatusCode == 412 || response.StatusCode == 409))
{
// Concurrency Exception - Entity Updated in-between
// by another thread, Fetch the latest _stat entity and repeat operation
}
else
{
// log it and come out of while loop
break;
}
}
catch (Exception)
{
// log it and come out of while loop
break;
}
}