繁体   English   中英

删除azure表存储行而不检查是否存在

[英]delete azure table storage row without checking for existence

我多年来一直在使用 azure 表存储,但我不确定使用最新的 WindowsAzure.Storage 库版本 5.0.1-preview 执行此操作的“正确”方法是什么(用于新的 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;
    }
}

问题:

  1. 异常本身将我指向这个 TranslateFromExceptionMessage 方法......我找不到关于它和 WrappedStorageException (抛出的异常的类型)的大量信息。 这是检查存储异常中的 404 错误的某种新的/首选方法吗? 有谁知道现在是否所有存储异常都会使用它,或者我是否需要编写代码来测试和弄清楚?

  2. 有一个 StorageException 类型的 InnerException。 大概我们使用 StorageException.RequestInformation.HttpStatusCode 的旧代码可以以相同的方式访问这个内部异常。 那是“OK”,还是以某种方式更好或更健壮地解析这些新的 XML 错误消息?

  3. 对于这种情况,我应该考虑完全不同的方法吗?

当配置为使用 Azure 表存储时,在 AspNet WebHooks 项目中可以找到类似的方法。 查看Microsoft.Aspnet.WebHooks.custom.AzureStorage StorageManager类。

我不确定这会在您已经发现的基础上增加多少,但它们处理所有内容而不会引发异常并始终返回状态代码,以便您可以根据需要做出反应。

这里的一个区别是它们将tableoperation传递给多用途的 ExecuteAsync 方法,而不是专门用于删除的方法,但这只是一个实现细节。

他们示例中的相关代码:

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

RequestResult.TranslateFromExceptionMessage方法现在被标记为[Obsolete] ,我想要一种自己忽略 404 的方法。

根据您查看RequestInformation.HttpStatusCode提示,我想出了以下内容:

try
{
    await table.ExecuteAsync(op);
}
catch (StorageException storEx)
{
    if (storEx.RequestInformation.HttpStatusCode != 404)
    {
        throw;
    }
}

如果您使用的是最新的客户端 ( Azure.Data.Tables ),则删除方法会自动吞下 404 响应并且不会抛出。 这种方法避免了编写引入竞争条件的代码(在执行操作之前首先检查)或必须使用 try/catch 块处理这种情况的需要。

如果您想知道该操作是实际删除了一个表还是它不存在,您可以检查响应的 Status 属性。

Response response = await tableClient.DeleteAsync();
if (response.Status == (int)HttpStatusCode.NotFound)
{
    // entity didn't exist)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM