问题描述
在以下情况下,我需要能够将实体插入到Azure存储表中:
I need to be able to insert an entity to an azure storage table under these conditions:
- 如果不存在,请插入.
- 如果存在,但我将ETag指定为*,则替换.
- 如果它存在,但是ETag具有另一个值,则抛出StorageException代码为409或412.(例如,我将尝试插入一个已检索到的实体,但同时它已从其他位置进行了更新)
我做了一个简单的程序来测试,但是我不知道如何使它工作.它永远不会达到例外.(我认为这是常规的ETag行为要求.)
I made this simple program to test, but I can't figure out how to get this to work. it never reaches the exception. (I thought this was regular ETag behavior requirements).
请注意,如果我使用Insert操作而不是InsertOrReplace,即使ETag的值不变,我也会收到异常.
Note that if I use Insert operation instead of InsertOrReplace I get an exception even if ETag has an unchanged value.
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.");
}
}
推荐答案
我可能已经找到了解决方案.如果没有更好的答案,将接受这一点.
I may have found a solution. Will accept this if nobody has a better answer.
我尝试添加 OperationContext
的 If-Match
标头,并以Etag作为值.这行得通.我以为这是自动添加的东西,但显然不是.
I tried to add If-Match
header of the OperationContext
, with the Etag as the value. This worked. I thought this was an automatically added thing, but apparently not.
testtable.Execute(
TableOperation.InsertOrReplace(firstRetrieve),
null,
new OperationContext {
UserHeaders = new Dictionary<String, String>
{
{ "If-Match", firstRetrieve.ETag }
}
}
);
现在,当将 null
用作ETag时,我可以插入或替换,它还可以正确地检查ETag是否还有其他内容.
Now, when using null
as ETag, I can InsertOrReplace, and it also properly checks ETag if it's something else.
请注意,如果我将 *
用作ETag,则如果该实体不存在,则会收到404异常.因此,使用 null
可获得预期的功能.或者只是检测 *
而不添加标题.
Note that if I use *
as ETag, I get a 404 exception if the entity doesn't exist. So use null
to get the intended functionality. Or just detect *
and don't add the header.
注意事项:如果您想插入一个新项目(ETag == null
),但仍想获取异常代码409冲突(如果已经存在),则必须使用插入
操作而不是 InsertOrReplace
操作.
Caveat: If you'd want to insert a new item (ETag == null
) but still want to get an exception code 409 conflict if it already exists, you must use the Insert
operation instead of the InsertOrReplace
operation.
这篇关于如果ETag不匹配,如何使用ETag在插入时引发异常(*时除外)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!