Azure Table 存储在插入时抛出异常:(409) 冲突
Azure Table Storage throwing exception on Insert: (409) Conflict
我正在使用 Azure Table 存储来记录来自我的 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);
更新
正如下面的评论和两个答案所指出的,问题是有时页面会快速连续加载两次,我使用 GUID(用户唯一的)作为分区键,而当前datetime 作为行键,因此这会导致重复实体并导致异常。
虽然Amor的回答比较深入,但Dogu的简单解决方案是我使用的,所以我标记他的正确。谢谢大家。
在 Azure Table 存储中,Partition Key + Row Key 一起作为进入 table 的主键,这个组合必须是唯一的。如果插入一行,其Partition Key和Row Key已经存在于table中。它将抛出 (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);
}
您可以尝试 InsertOrReplace
而不是 Insert
以避免 409,如果实体不存在,它将插入实体,如果存在,则替换现有实体。需要注意的是它不检查 eTag s,因此如果存在具有相同分区键和行键的现有实体,它会无条件地覆盖它。
我处理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;
}
}
希望对您有所帮助!
我正在使用 Azure Table 存储来记录来自我的 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);
更新
正如下面的评论和两个答案所指出的,问题是有时页面会快速连续加载两次,我使用 GUID(用户唯一的)作为分区键,而当前datetime 作为行键,因此这会导致重复实体并导致异常。
虽然Amor的回答比较深入,但Dogu的简单解决方案是我使用的,所以我标记他的正确。谢谢大家。
在 Azure Table 存储中,Partition Key + Row Key 一起作为进入 table 的主键,这个组合必须是唯一的。如果插入一行,其Partition Key和Row Key已经存在于table中。它将抛出 (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);
}
您可以尝试 InsertOrReplace
而不是 Insert
以避免 409,如果实体不存在,它将插入实体,如果存在,则替换现有实体。需要注意的是它不检查 eTag s,因此如果存在具有相同分区键和行键的现有实体,它会无条件地覆盖它。
我处理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;
}
}
希望对您有所帮助!