插入时的Azure表存储抛出异常:(409)冲突

lit*_*rva 5 azure azure-table-storage

我正在使用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
Run Code Online (Sandbox Code Playgroud)

这似乎发生在我第一次访问网站一段时间不活动后,然后当我点击刷新,页面加载,从那时起的每次点击都很好.

以下是导致异常的代码部分:

  var visit = new TrackerVisitEntity(id, url, referer);
  var insertOperation = TableOperation.Insert(visit);
  _table.Execute(insertOperation);
Run Code Online (Sandbox Code Playgroud)

更新

正如下面的注释和两个答案所述,问题是有时页面连续快速加载两次,我使用GUID(用户独有)作为分区键,当前日期时间作为行键,这会导致重复的实体并导致异常.

虽然Amor的回答更加深入,但Dogu的简单解决方案就是我使用过的,所以我标记了他的正确答案.感谢大家.

Dog*_*lan 7

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


Amo*_*mor 6

在Azure表存储中,分区键+行键共同充当表中该条目的主键,此组合必须唯一。如果插入一行,其分区键和行键在表中已经存在。它将抛出(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");
    }
}
Run Code Online (Sandbox Code Playgroud)

如果再次发生异常,跟踪信息将显示分区键和行键是否已经存在。

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

catch (StorageException ex)
{
    Trace.TraceInformation(ex.RequestInformation.ExtendedErrorInformation.ErrorMessage); 
}
Run Code Online (Sandbox Code Playgroud)