问题
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.
回答1:
You could try InsertOrReplace
instead of Insert
to 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.
回答2:
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);
}
回答3:
The way I've handled 409 errors is to catch
the specific HttpStatusCode
as follows:
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;
}
}
Hope this helps!
来源:https://stackoverflow.com/questions/44799524/azure-table-storage-throwing-exception-on-insert-409-conflict