【问题标题】:Azure Table Storage throwing exception on Insert: (409) ConflictAzure 表存储在插入时抛出异常:(409) 冲突
【发布时间】:2017-06-28 10:08:09
【问题描述】:

我正在使用 Azure 表存储从我的 MVC 应用程序记录访问者信息,但它有时会引发以下异常:

[WebException: The remote server returned an error: (409) Conflict.]
   System.Net.HttpWebRequest.GetResponse() +1399
   Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync(RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Core\Executor\Executor.cs:677

[StorageException: The remote server returned an error: (409) Conflict.]
   Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync(RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Core\Executor\Executor.cs:604
   Microsoft.WindowsAzure.Storage.Table.TableOperation.Execute(CloudTableClient client, CloudTable table, TableRequestOptions requestOptions, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Table\TableOperation.cs:44

当我在一段时间不活动后第一次访问该网站时似乎会发生这种情况,然后当我点击刷新时,页面加载并且从那时起每次点击都很好。

这是导致异常的代码部分:

  var visit = new TrackerVisitEntity(id, url, referer);
  var insertOperation = TableOperation.Insert(visit);
  _table.Execute(insertOperation);

更新

正如 cmets 和下面的两个答案中所确定的,问题是有时页面会快速连续加载两次,并且我使用 GUID(用户唯一)作为分区键,当前日期时间为行键,所以这会导致重复实体并导致异常。

虽然 Amor 的回答比较深入,但 Dogu 的简单解决方案是我使用的,所以我标记了他的正确。谢谢大家。

【问题讨论】:

  • 收到此错误时能否请您检查实体是否存在?
  • 你使用什么作为 RowKey 和 PartitionKey?
  • 请检查Gaurav提到的实体是否已经存在。

标签: azure azure-table-storage


【解决方案1】:

您可以尝试InsertOrReplace 而不是Insert 来避免409,如果实体不存在,它将插入实体,如果存在则替换现有实体。需要注意的是它不检查 eTag ,因此如果存在具有相同分区键和行键的现有实体,它将无条件地覆盖它。

【讨论】:

  • 如何在不替换的情况下添加多个图像的partitionkey和rowkey?
【解决方案2】:

在 Azure 表存储中,Partition Key + Row Key 一起作为该表项的主键,这个组合必须是唯一的。如果插入一行,其 Partition Key 和 Row Key 已经存在于表中。它将抛出(409)冲突异常。您可以使用以下代码进行确认。

var visit = new TrackerVisitEntity(id, url, referer);

var insertOperation = TableOperation.Insert(visit);
try
{
    _table.Execute(insertOperation);
}
catch (StorageException ex)
{
    Trace.TraceInformation(string.Format("PartitionKey:{0},RowKey:{1}", visit.PartitionKey,visit.RowKey));
    TableOperation retrieveOperation = TableOperation.Retrieve<TrackerVisitEntity>(visit.PartitionKey, visit.RowKey);
    TableResult retrievedResult = _table.Execute(retrieveOperation);
    if (retrievedResult.Result != null)
    {
        Trace.TraceInformation("The entity is already exists in Table");
    }
}

如果再次发生异常,trace信息会显示Partition Key和Row Key是否已经存在。

您还可以从 RequestInformation.ExtendedErrorInformation.ErrorMessage 中获取详细的异常消息。

catch (StorageException ex)
{
    Trace.TraceInformation(ex.RequestInformation.ExtendedErrorInformation.ErrorMessage); 
}

【讨论】:

    【解决方案3】:

    我处理409错误的方式是catch具体HttpStatusCode如下:

    public TableResult AddAudioTest(AudioTestModel audioTestModel)
        {
            azureTableStorage = AzureTableStorage.TableConnection("AudioTests");
            TableOperation tableOperation = TableOperation.Insert(audioTestModel);
            try
            {
                TableResult tableInsertResult = azureTableStorage.Execute(tableOperation);
                return tableInsertResult;
            }
            catch (Microsoft.WindowsAzure.Storage.StorageException e) when (e.RequestInformation.HttpStatusCode == 409)
            {
                TableResult tableResult = new TableResult();
                tableResult.HttpStatusCode = e.RequestInformation.;
                tableResult.Result = e.Message;
                return tableResult;
            }
        }
    

    希望这会有所帮助!

    【讨论】:

    • 似乎Execute方法在抛出和返回时不一致,TableResult.Result设置为null + TableResult.HttpStatusCode设置为4xx。前一种情况出现 412 错误,后一种情况出现 404 错误。
    猜你喜欢
    • 2018-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多