我们有一个解决方案,我们并行读写Azure表存储。
因为TableServiceContext不支持在一个线程上读取实体并将其保存在另一个线程上,所以我们希望使用另一个上下文来保持实体。为此,我们需要设置:
context.MergeOption = MergeOption.NoTracking;
当更新(或删除)一个实体时,我们调用:
context.AttachTo(entitySetName, entity, eTag);
然而,要做到这一点,我们需要知道ETag,我不知道如何得到它。
如果实体被跟踪,我们可以使用entitydescriptor。ETag像这样:
private string GetETagFromEntity<T>(T entity) where T : TableServiceEntity
{
return context.Entities.Single(entityDescriptor =>
entityDescriptor.Entity == entity).ETag;
}
…但上下文。实体是空的,因为我们不跟踪实体。
迄今为止我们找到的唯一解是:
context.AttachTo(entitySetName, entity, "*");
…但这意味着我们有并发问题,最后写的总是赢。
我们还尝试构建以下在本地计算模拟器上工作但不能在云中工作的代码:
private string GetETagFromEntity<T>(T entity) where T : TableServiceEntity
{
string datePart = entity.Timestamp.ToString("yyyy-MM-dd");
string hourPart = entity.Timestamp.ToString("HH");
string minutePart = entity.Timestamp.ToString("mm");
string secondPart = entity.Timestamp.ToString("ss");
string milisecondPart = entity.Timestamp.ToString("fff").TrimEnd('0');
return string.Format(
"W/"datetime'{0}T{1}%3A{2}%3A{3}.{4}Z'"",
datePart,
hourPart,
minutePart,
secondPart,
milisecondPart
).Replace(".Z", "Z");
}
这种方法的一般问题是,即使我们可以让它工作,微软并没有对ETag的外观做出任何保证,所以这可能会随着时间的推移而改变。
那么问题是:我们如何获得未被跟踪的Azure表存储实体的ETag ?
我想你在阅读实体时必须注意etag。(可能有一个事件,你可以挂钩,也许ReadingEntity,你可以访问etag和存储它的地方)
我已经编写了一个替代表存储客户端,它非常明确地公开了etag,并且可以使用上下文无关并且线程安全。它可以为您工作。