将对象更新为Azure表存储 - 有没有办法获得新的时间戳?

时间:2011-03-31 12:52:23

标签: azure azure-storage azure-table-storage

我正在使用带有

的StorageClient库更新AzureTableStorage中的对象
    context.UpdateObject(obj);
    context.SaveChangesWithRetries(obj);

当我这样做时,有没有办法获取obj的新时间戳而不向服务器发送另一个请求?

由于

斯图尔特

5 个答案:

答案 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

您可以查看操作结果以获取eTagTimespan属性:

var tableResult = cloudTable.Execute(TableOperation.Replace(entity));
var updatedEntity = tableResult.Result as ITableEntity;

var eTag = updatedEntity.ETag;
var timestamp = updatedEntity.Timestamp;