我已经使用azure表存储多年了,我不确定用最新的WindowsAzure做这件事的"正确"方法是什么。存储库,版本5.0.1-预览版(用于新的ASP。. NET 5应用程序):
问题:给定一个分区键和行键,删除该行时不首先检查该行是否存在,如果该行不存在也不会失败。
当前解决方案:但是异常处理令人困惑:
public async Task DeleteRowAsync(CloudTable table, string partition, string row)
{
var entity = new DynamicTableEntity(partition, row);
entity.ETag = "*";
var op = TableOperation.Delete(entity);
try
{
await table.ExecuteAsync(op);
}
catch (Exception ex)
{
var result = RequestResult.TranslateFromExceptionMessage(ex.Message);
if (result == null || result.HttpStatusCode != 404)
throw ex;
}
}
问题:
异常本身指向我这个TranslateFromExceptionMessage方法…我找不到关于它和WrappedStorageException(抛出的异常类型)的大量信息。这是一种新的/首选的方式来检查存储异常的404错误吗?有人知道是否所有的存储异常现在将使用这个,或者我需要写代码来测试和弄清楚吗?
有一个类型为StorageException的InnerException。假设使用StorageException.RequestInformation.HttpStatusCode的旧代码可以以相同的方式访问这个内部异常。这样可以吗?或者解析这些新的XML错误消息是否更好或更健壮?
对于这种情况,我是否应该考虑另一种方法?
如果您使用的是最新的客户端(Azure.Data.Tables),则delete方法会自动吞下404响应而不会抛出。这种方法避免了编写引入竞争条件的代码(在执行操作之前先检查),也避免了使用try/catch块来处理这种条件。
如果你想知道操作是否真的删除了一个表或者它不存在,你可以检查响应的Status属性。
Response response = await tableClient.DeleteAsync();
if (response.Status == (int)HttpStatusCode.NotFound)
{
// entity didn't exist)
}
RequestResult.TranslateFromExceptionMessage
方法现在标记为[Obsolete]
,我想要一种方法来忽略404的自己。
根据你的提示检查RequestInformation.HttpStatusCode
,我想出了以下内容:
try
{
await table.ExecuteAsync(op);
}
catch (StorageException storEx)
{
if (storEx.RequestInformation.HttpStatusCode != 404)
{
throw;
}
}
在配置为使用Azure表存储时,在asp.net WebHooks项目中发现了类似的方法。请看Microsoft.Aspnet.WebHooks.custom.AzureStorage
StorageManager类
我不确定这在你已经发现的基础上增加了多少,但是它们处理一切而不抛出异常,并且总是返回一个状态码,所以你可以在必要时对它做出反应。
这里的一个区别是它们将table
和operation
传递给一个多用途的ExecuteAsync方法,而不是一个专门用于delete的方法,但这只是一个实现细节。
示例中的相关代码:
public async Task<TableResult> ExecuteAsync(CloudTable table, TableOperation operation)
{
if (table == null)
{
throw new ArgumentNullException(nameof(table));
}
if (operation == null)
{
throw new ArgumentNullException(nameof(operation));
}
try
{
var result = await table.ExecuteAsync(operation);
return result;
}
catch (Exception ex)
{
var errorMessage = GetStorageErrorMessage(ex);
var statusCode = GetStorageStatusCode(ex);
var message = string.Format(CultureInfo.CurrentCulture, AzureStorageResources.StorageManager_OperationFailed, statusCode, errorMessage);
_logger.Error(message, ex);
return new TableResult { HttpStatusCode = statusCode };
}
}
public string GetStorageErrorMessage(Exception ex)
{
if (ex is StorageException storageException && storageException.RequestInformation != null)
{
var status = storageException.RequestInformation.HttpStatusMessage != null ?
storageException.RequestInformation.HttpStatusMessage + " " :
string.Empty;
var errorCode = storageException.RequestInformation.ExtendedErrorInformation != null ?
"(" + storageException.RequestInformation.ExtendedErrorInformation.ErrorMessage + ")" :
string.Empty;
return status + errorCode;
}
else if (ex != null)
{
return ex.Message;
}
return string.Empty;
}
public int GetStorageStatusCode(Exception ex)
{
return ex is StorageException se && se.RequestInformation != null ? se.RequestInformation.HttpStatusCode : 500;
}