C# Azure Function v2在处理StorageException后始终返回内部服务器错误500
假设您有一个使用表存储的Azure函数(v2),您运行该函数,但存在具有SomePartitionKey/SomeRowKey的实体(例如,您运行以下两次):C# Azure Function v2在处理StorageException后始终返回内部服务器错误500,c#,error-handling,azure-functions,C#,Error Handling,Azure Functions,假设您有一个使用表存储的Azure函数(v2),您运行该函数,但存在具有SomePartitionKey/SomeRowKey的实体(例如,您运行以下两次): [FunctionName(“SomeEntity”)] 公共静态异步任务运行([HttpTrigger(AuthorizationLevel.Anonymous,“post”,Route=“someentity”)]HttpRequest请求, [表(“某些实体”)]IAsyncCollector收集器, ILogger(记录器) {
[FunctionName(“SomeEntity”)]
公共静态异步任务运行([HttpTrigger(AuthorizationLevel.Anonymous,“post”,Route=“someentity”)]HttpRequest请求,
[表(“某些实体”)]IAsyncCollector收集器,
ILogger(记录器)
{
尝试
{
SomeEntity se=新的SomeEntity()
{
PartitionKey=“SomePartitionKey”,
RowKey=“SomeRowKey”
};
等待收集器AddAsync(se);
等待收集器。FlushAsync();
返回新的OkResult();
}
捕获(Microsoft.WindowsAzure.Storage.StorageException e)
{
logger.LogError(“处理请求时出错。”,e);
返回新的StatusCodeResult(409);
}
}
当此操作运行且实体已存在时(如预期的那样),它将抛出StorageException。我的问题是,即使我捕捉到异常并尝试返回StatusCodeResult(409)
,发送到客户端的实际响应始终是一个内部服务器错误(500)
我的问题是:a) 这是函数试图再次在收集器上调用
FlushAsync()
的清理逻辑导致未处理的StorageException的结果,该异常会导致内部服务器错误(500)。
b) 如果a)是,是否可以防止这种情况发生?c) 除了首先检查实体是否存在外,对于这种情况是否有任何最佳实践?Azure函数NuGet软件包的一大优点是它们启用了源链接。确保在VisualStudio选项中选中了
启用源代码链接支持
,您将能够准确地看到他们的代码在做什么。函数应用程序运行后,您可以选择在引发任何CLR异常时中断
如果您这样做,您将看到异常按照预期从FlushAsync
抛出,您的代码正在捕获它,并返回409结果。然后,在函数返回后,再次抛出相同的异常(因为在函数外部再次调用了FlushAsync
),捕获该异常,并在处理函数返回后的参数收集器时抛出一个包装异常,其中包含消息Error,在执行函数:SomeEntity
时,会捕获该函数,并抛出一个包装器异常和消息异常,然后捕获该函数,并向客户端返回一个普通的old 500错误
因此:
a) 这是函数尝试在收集器上再次调用FlushAsync()的清理逻辑的结果,导致未处理的StorageException,从而导致内部服务器错误(500)
对。如果启用源链接支持并在抛出时中断,则可以通过Azure函数运行时进行调试,并看到这种情况发生
b) 如果a)为是,是否可以防止这种情况
c) 除了首先检查实体是否存在外,是否存在此场景的最佳实践
我不建议先检查后插入。你将以比赛条件而告终
发件人:
此输出绑定不支持更新现有实体。使用Azure Storage SDK中的TableOperation.Replace
操作更新现有实体
一般来说,任何给定服务的Azure函数绑定都是针对简单用例的。在Azure存储表的情况下,简单的用例只是插入实体
但是,您始终可以自己使用存储SDK。无论如何,这正是绑定为您所做的。这个绑定也会进行一些批处理,但如果需要的话,实现起来并不难
您还可以执行“中途”:将表绑定到CloudTable
而不是IAsyncCollector
。这样,您将自动使用适当的连接字符串;您只需编写自己的TableOperation.InsertOrReplace
code。您是否尝试捕获所有异常?然后找出需要捕获哪些异常?顺便问一下,为什么要刷新收集器???捕获所有异常会导致相同的行为。我正在刷新以在函数退出之前强制将add添加到DB中,这样我就可以检测错误,比如这个异常,这样我就可以记录错误,理想情况下,向客户端返回一个有意义的错误代码,而不是500错误。添加是在函数外部完成的,因此如果刷新收集器,它将无法工作。感谢Stephen的详细回答以及@Thomas。当我已经显式地调用了FlushAsync()
时,我想我没有料到函数退出后会有第二次调用FlushAsync()
。我将介绍CloudTable绑定的使用。
[FunctionName("SomeEntity")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "someentity")] HttpRequest req,
[Table("SomeEntities")] IAsyncCollector<SomeEntity> collector,
ILogger logger)
{
try
{
SomeEntity se = new SomeEntity()
{
PartitionKey = "SomePartitionKey",
RowKey = "SomeRowKey"
};
await collector.AddAsync(se);
await collector.FlushAsync();
return new OkResult();
}
catch (Microsoft.WindowsAzure.Storage.StorageException e)
{
logger.LogError("There was an error processing the request.", e);
return new StatusCodeResult(409);
}
}