我有一个程序可以更新Azure表存储表中的条目,如下所示:
- 通过partitionKey和itemId从表筛选中恢复条目
- 对已恢复对象的某些属性进行一些更改
- 将更改保存回BD
因为我读到Azure存储表使用乐观并发性和Etag属性(例如,根据这个,或者这个关于Etag中存储的内容的stackoverflow问题(为了管理它,我想出了这个代码:
var query = table.CreateQuery<DynamicTableEntity>()
.Where(d => d.PartitionKey == customItem.PartitionKey
&& d.Properties[nameof(CustomItem.CustomItemId)].GuidValue == Guid.Parse(StringValueOfId)
)
.AsTableQuery();
var tr = table.ExecuteQuery<DynamicTableEntity>(query);
if (tr != null)
{
var entity = new DynamicTableEntity(customItem.PartitionKey, StringValueOfId);
entity.Properties.Add("MyDate", dateValue);
entity.Properties.Add("CustomProperty", new EntityProperty(JsonConvert.SerializeObject(customItem)));
entity.ETag = tr.FirstOrDefault().ETag;
TableOperation mergeOperation = TableOperation.Replace(entity);
try
{
TableResult result = await table.ExecuteAsync(mergeOperation);
}
catch (Exception ex)
{
throw new StorageException("Error saving data:" + ex.Message);
}
}
现在我仍然有并发问题。基本上是我的";CustomProperty"有某些字段为null的序列化属性。看起来A和B都试过了以设置"0"的值;CustomProperty"同时其中一个是重写另一个的变化。
然而,我预计由于";实体ETag";。我预计,如果A和B在BD的同时读取,然后A更新,由于实体的值不匹配,B的更新将失败。ETag。
有人能告诉我我做错了什么吗?我是否不明白如何正确避免这些一致性问题?
我发现了问题所在。这条线有错误的etag:
entity.ETag = tr.FirstOrDefault().ETag;
这是当我从DB中读取行以恢复要更新的项时的Etag,但实际上我需要当我读取customItem属性时的Etag值。
否则,这一行可能会覆盖在我恢复customItem,但在我执行查询var tr=table之前。ExecuteQuery(查询(
entity.Properties.Add("CustomProperty", new EntityProperty(JsonConvert.SerializeObject(customItem)));
换句话说,这解决了我的问题:
entity.ETag = customItem.ETag