如果ETag不匹配,如何使用ETag在插入时引发异常(*时除外) [英] How to use ETag to throw exception on insert if ETag doesn't match (except when it's *)

查看:40
本文介绍了如果ETag不匹配,如何使用ETag在插入时引发异常(*时除外)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下情况下,我需要能够将实体插入到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在插入时引发异常(*时除外)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆