Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Azure Table Storage throwing exception on Insert: (409) Conflict

I'm using Azure Table Storage to log visitor information from my MVC app, but it sometimes throws the following exception:

[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

It seems to happen when I first visit the website after a period of inactivity, then when I hit refresh, the page loads and every click from then on is fine.

Here is the part of the code that's causing the exception:

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

Update

As identified in the comments AND both answers below, the problem is that sometimes the page is loaded twice in quick succession, and I'm using a GUID (unique to the user) as the partition key, and the current datetime as the row key, so this is causing duplicate entities and causing the exception.

Although Amor's answer was more indepth, Dogu's simple solution was the one I used, so I marked his correct. Thanks everyone.

like image 402
littlecharva Avatar asked Jun 28 '17 10:06

littlecharva


2 Answers

You could try InsertOrReplace instead of Insertto avoid 409, it is going to insert the entity if it does not exist and replace the existing one if it exists. The caveat with that is it does not check eTag s, so if there is an existing entity with the same partition key and row key it unconditionally overwrites it.

like image 167
Dogu Arslan Avatar answered Nov 10 '22 03:11

Dogu Arslan


In Azure Table Storage, The Partition Key + the Row Key together act as a primary key for that entry into the table, this combination must be unique. If you insert a row whose Partition Key and Row Key are already exist in the table. It will throw (409) Conflict exception. You could confirm it using following code.

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");
    }
}

If the exception happens again, the trace information will show that whether Partition Key and Row Key are already exist.

You can also get the detail exception message from RequestInformation.ExtendedErrorInformation.ErrorMessage.

catch (StorageException ex)
{
    Trace.TraceInformation(ex.RequestInformation.ExtendedErrorInformation.ErrorMessage); 
}
like image 44
Amor Avatar answered Nov 10 '22 02:11

Amor