Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Azure Function v2在处理StorageException后始终返回内部服务器错误500_C#_Error Handling_Azure Functions - Fatal编程技术网

C# Azure Function v2在处理StorageException后始终返回内部服务器错误500

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(记录器) {

假设您有一个使用表存储的Azure函数(v2),您运行该函数,但存在具有SomePartitionKey/SomeRowKey的实体(例如,您运行以下两次):

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