许多嵌套的aggregateexception

本文关键字:aggregateexception 嵌套 许多 | 更新日期: 2023-09-27 17:49:02

使用Entity Framework 7时,我在linq上犯了一个简单的错误(使用Skip,忘记包含OrderBy子句)。

由this抛出的异常包括许多嵌套的聚合异常。

生成(并捕获)异常的代码是:
int[] newIds;
try
{
    newIds = await db.Products
        .Where(p => p.PortalId == portalId)
        .Skip(ids.ProductIds.Count) //Skip the rows already read
        .Take(takeTotal) //get the next block
        .Select(p => p.ProductId)
        .ToArrayAsync();
}
catch (AggregateException ex)
{
    Console.WriteLine(ex.Message);
    newIds = new int[] { };
}

上面的代码在一个从Asp. js调用的repo类中。Net 5 WebApi控制器。所有级别的调用都使用async-await。

然而,我从这里得到的聚合异常是(这是从上面所示的catch块转储到直接窗口):

系统。AggregateException:发生了一个或多个错误。--->系统。AggregateException:发生了一个或多个错误。--->系统。AggregateException:发生了一个或多个错误。--->系统。AggregateException:发生了一个或多个错误。--->系统。AggregateException:发生了一个或多个错误。--->系统。AggregateException:发生了一个或多个错误。--->系统。InvalidOperationException:包含Skip操作符的查询必须包含至少一个OrderBy操作。在Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.GenerateLimitOffset (SelectExpressionselectExpression)Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.VisitSelectExpression (SelectExpressionselectExpression)Microsoft.Data.Entity.Relational.Query.Expressions.SelectExpression.Accept (ExpressionTreeVisitor访客)Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.GenerateSql (SelectExpressionselect表达式,字典' 2参数值等等

在这里,实际的异常最终被一大堆聚集异常层(6个嵌套层)包裹起来。我理解为什么我得到了一个汇总异常,但想知道为什么有这么多异常?更重要的是,在它冒泡回到控制器入口点之前,我正在查看异常。

这将是许多层的async-await的结果,(不认为我有多达6)或它可能是一个问题在EF7的实现?

当前使用的是EF 7 7.0.0-beta4版本

许多嵌套的aggregateexception

正如MSDN页面上Task<T>解释的那样,Task抛出的所有异常在被抛出到等待代码之前都被AggregateException包装。如果你使用多个级别的async/await并且没有在尽可能低的级别捕获此异常,那么每次它出现在另一个级别时,它将再次被包装,导致AggregateExceptionAggregateException中,每次你等待而没有捕获。

也可以将每个操作算作自己的任务;ie。每次添加另一个操作时,结果都会从前一个操作中取出,并返回到下一个操作中,每个操作都等待前一个操作。看一下:

newIds = await db.Products               // 1
    .Where(p => p.PortalId == portalId)  // 2
    .Skip(ids.ProductIds.Count)          // 3
    .Take(takeTotal)                     // 4
    .Select(p => p.ProductId)            // 5
    .ToArrayAsync();                     // 6

六层东西,每一层都在等待前一层的结果。6个AggregateException层。现在,您的异常是由六个中的第三个引起的,但是从错误的性质来看,它很可能来自EF在执行任何查询之前读取整个查询的部分,并且在这样做时发现您有一个.Skip()而没有匹配的.OrderBy()

正如Stephen Cleary在评论中提醒我的那样,虽然await返回Task<T>,但它们也为您做了一定程度的解包装,因此await的行为不太像Task<T>.Result,这意味着await 应该抛出实际的异常,而不将其包装在AggregateException中。这一切意味着我们最多只能得到一半的答案(这有点尴尬,因为它已经被接受了)。老实说,我建议你不要接受这个答案,这样别人就不会跳过你的问题,并看看是否有人知道一些可能填补空白的东西。

这与链中调用的方法数量无关。你只需要调用ToArrayAsync。

我认为问题出在Rx.NET。我发送了一个Pull Request来修复它:https://github.com/aspnet/EntityFramework/issues/2192

https://github.com/Reactive-Extensions/Rx.NET/pull/131/files

相关文章:
  • 没有找到相关文章