我正在使用带有
的StorageClient库更新AzureTableStorage中的对象 context.UpdateObject(obj);
context.SaveChangesWithRetries(obj);
当我这样做时,有没有办法获取obj
的新时间戳而不向服务器发送另一个请求?
由于
斯图尔特
答案 0 :(得分:13)
MSDN page对Timestamp字段的使用有一些指导:
时间戳属性
Timestamp属性是DateTime 在服务器上维护的值 一边记录一个实体的时间 最后修改。 Table服务使用 内部的Timestamp属性 提供乐观的并发性。 您 应该将此属性视为不透明: 不应该阅读,也不应该开启 插入或更新操作(值 将被忽略)。
这意味着它实际上是表存储的实现细节,您不应该依赖Timestamp字段来表示上次更新的时间戳。
如果您想要一个保证代表上次写入时间的字段,请创建新字段并在每次更新操作时设置它。我理解这是维护字段的更多工作(以及更多存储空间),但这实际上会自动解决您的问题 - 如何获取时间戳,因为您在调用context.UpdateObject()时已经知道它。
答案 1 :(得分:13)
补充Seva Titov's answer:所报告的摘录至少有效期至2013年5月,但截至2013年11月已发生变化(强调已添加):
Timestamp属性是在服务器端维护的DateTime值,用于记录上次修改实体的时间。 Table服务在内部使用Timestamp属性来提供乐观并发。 Timestamp的值是一个单调递增的值,这意味着每次修改实体时,该实体的Timestamp值都会增加。不应在插入或更新操作上设置此属性(将忽略该值)。
现在Timestamp
属性不再被视为不透明,并且记录了每次编辑后其值增加 - 这表明现在可以使用Timestamp
来跟踪后续更新(至少关于单一实体)。
尽管如此,截至2013年11月,在更新实体时仍需要另一个表存储请求来获取新的时间戳(请参阅Update Entity REST方法的文档)。仅当inserting an entity REST服务返回带有时间戳的整个实体时(但我不记得它是否由StorageClient / Windows Azure存储库公开)。
答案 2 :(得分:4)
Timestamp
属性实际上是Lamport timestamp。它保证会随着时间的推移而不断增长,虽然它以DateTime
值显示但实际上并非如此。
在服务器端,即Windows Azure存储,每次更改都会执行此操作:
nextTimestamp = Math.Max(currentTimestamp + 1, DateTime.UtcNow)
这就是它的全部。它当然保证以交易方式发生。所有这一切的要点是提供一个逻辑时钟(单调函数),可用于确保事件的顺序按预期顺序发生。
这里是指向实际WAS paper版本的链接,虽然它没有包含有关时间戳方案的任何信息,但具体上它有足够的东西可以让您快速意识到这里有'你可以从中得出一个合乎逻辑的结论。其他任何东西都是愚蠢的。此外,如果你有任何LevelDB,Cassandra,Memtables及其类似的经验,你会发现WAS团队走的是相同的路线。
虽然我应该补充说明,因为WAS提供了强大的一致性模型,维护时间戳的唯一方法是在锁定和密钥下进行,所以你无法猜出正确的下一个时间戳。您必须查询WAS以获取信息。没有办法解决这个问题。但是,您可以保留旧值并假设它没有变化。 WAS会告诉你它是否可以,然后你可以以任何你认为合适的方式解决竞争条件。
答案 3 :(得分:0)
我不这么认为,据我所知,Timespan和Etag是由Azure Storage本身设置的。
答案 4 :(得分:0)
我正在使用Windows Azure Storage 7.0.0
您可以查看操作结果以获取eTag
和Timespan
属性:
var tableResult = cloudTable.Execute(TableOperation.Replace(entity));
var updatedEntity = tableResult.Result as ITableEntity;
var eTag = updatedEntity.ETag;
var timestamp = updatedEntity.Timestamp;