我需要能够在以下条件下将实体插入到azure存储表中:
我制作了这个简单的程序进行测试,但我无法弄清楚如何让它工作。它永远不会达到例外。 (我认为这是常规的ETag行为要求)。
请注意,如果我使用Insert操作而不是InsertOrReplace,即使ETag的值不变,我也会得到异常。
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnString);
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
tableClient.RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 10);
var testtable = tableClient.GetTableReference("davidstesttable");
testtable.CreateIfNotExists();
//insert first entity
var newentity = new DynamicTableEntity("idunno", String.Empty, "*", new Dictionary<string, EntityProperty> { { "testprop", new EntityProperty("testval") } });
Msg("insert initial entity");
testtable.Execute(TableOperation.InsertOrReplace(newentity));
Msg("inserted");
Msg("retrieving");
TableResult tableResult = testtable.Execute(TableOperation.Retrieve("idunno", String.Empty));
DynamicTableEntity firstRetrieve = (DynamicTableEntity)tableResult.Result;
Msg("retrieved. etag: " + firstRetrieve.ETag);
Msg("inserting the initial entity again to change the ETag in the table");
testtable.Execute(TableOperation.InsertOrReplace(newentity));
Msg("inserted");
Msg("retrieving");
TableResult tableResult2 = testtable.Execute(TableOperation.Retrieve("idunno", String.Empty));
DynamicTableEntity secondRetrieve = (DynamicTableEntity)tableResult2.Result;
Msg("retrieved. etag: " + secondRetrieve.ETag);
if(firstRetrieve.ETag != secondRetrieve.ETag)
{
Msg("confirmed entity in table now has different etag");
Msg("inserting the first retrieved. (etags should not match now, expecting StorageException)");
try
{
//If I use Insert operation instead of InsertOrReplace, I do get the exception,
//but I tested with this and then I get the exception even if the ETag is unchanged or * !
testtable.Execute(TableOperation.InsertOrReplace(firstRetrieve));
Msg("hmm should not have reached here!");
}
catch (StorageException e)
{
if(e.RequestInformation.HttpStatusCode == 409 || e.RequestInformation.HttpStatusCode == 412)
Msg("got exception as expected because of the mismatching ETag.");
}
}
答案 0 :(得分:10)
我可能找到了解决方案。如果没有人有更好的答案,我会接受这个。
我尝试添加If-Match
的{{1}}标头,并将Etag作为值。这很有效。我认为这是一个自动添加的东西,但显然不是。
OperationContext
现在,当使用testtable.Execute(
TableOperation.InsertOrReplace(firstRetrieve),
null,
new OperationContext {
UserHeaders = new Dictionary<String, String>
{
{ "If-Match", firstRetrieve.ETag }
}
}
);
作为ETag时,我可以使用InsertOrReplace,并且还可以正确检查ETag是否为其他内容。
请注意,如果我使用null
作为ETag,如果实体不存在,我会得到404异常。因此,使用*
来获取预期的功能。或者只是检测null
并且不添加标题。
编辑:
警告:如果您想要插入新项目(ETag == *
)但仍希望获得异常代码409冲突(如果已存在),则必须使用{{1} }操作而不是null
操作。