许多嵌套的聚合异常
Many nested AggregateExceptions
使用 Entity Framework 7,我在一些 linq 上犯了一个简单的错误(使用了 Skip 并忘记包含我的 OrderBy 子句)。
由此引发的异常包括多个嵌套聚合异常。
生成(并捕获)异常的代码是:
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.Net 5 WebApi 控制器调用的 repo class 中。所有级别的调用都使用 async-await。
然而,我从中得到的聚合异常是(从上面显示的 catch 块转储到立即 window):
System.AggregateException: One or more errors occurred. --->
System.AggregateException: One or more errors occurred. --->
System.AggregateException: One or more errors occurred. --->
System.AggregateException: One or more errors occurred. --->
System.AggregateException: One or more errors occurred. --->
System.AggregateException: One or more errors occurred. --->
System.InvalidOperationException: A query containing the Skip operator
must include at least one OrderBy operation. at
Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.GenerateLimitOffset(SelectExpression
selectExpression) at
Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.VisitSelectExpression(SelectExpression
selectExpression) at
Microsoft.Data.Entity.Relational.Query.Expressions.SelectExpression.Accept(ExpressionTreeVisitor
visitor) at
Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.GenerateSql(SelectExpression
selectExpression, IDictionary`2 parameterValues)
etc etc
这里实际的异常已经被一大堆聚合异常层(6 个嵌套层)包裹起来。我明白为什么我会得到一个聚合异常,但想知道为什么会有这么多异常?更重要的是,因为在异常冒泡回到控制器入口点之前我正在查看异常。
这是否是多层异步等待的结果(我认为我没有多达 6 层)还是 EF7 实现中的问题?
目前使用的是 EF 7 版本 7.0.0-beta4。
正如 the MSDN page on Task<T>
所解释的那样,Task
抛出的所有异常在被抛出到等待代码之前都包含在 AggregateException
中。如果您使用多个 async/await 级别并且没有在尽可能低的级别捕获此异常,那么每次它冒泡到另一个级别时,它都会再次包装,导致 AggregateException
在 AggregateException
, 每次等待没抓到一个.
也可能是每个操作都算作自己的任务; 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
六层事物,每一层都在等待上一层的结果。六 AggregateException
层。现在,您的异常是由六个中的第三个引起的,但从错误的性质来看,它很可能来自 EF 在执行任何查询之前读取您的整个查询的部分,并且在这样做时发现您'我有一个 .Skip()
没有匹配的 .OrderBy()
。
正如 Stephen Cleary 在评论中提醒我的那样,虽然你 await
return 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
使用 Entity Framework 7,我在一些 linq 上犯了一个简单的错误(使用了 Skip 并忘记包含我的 OrderBy 子句)。
由此引发的异常包括多个嵌套聚合异常。
生成(并捕获)异常的代码是:
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.Net 5 WebApi 控制器调用的 repo class 中。所有级别的调用都使用 async-await。
然而,我从中得到的聚合异常是(从上面显示的 catch 块转储到立即 window):
System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: A query containing the Skip operator must include at least one OrderBy operation. at Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.GenerateLimitOffset(SelectExpression selectExpression) at Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.VisitSelectExpression(SelectExpression selectExpression) at Microsoft.Data.Entity.Relational.Query.Expressions.SelectExpression.Accept(ExpressionTreeVisitor visitor) at Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.GenerateSql(SelectExpression selectExpression, IDictionary`2 parameterValues) etc etc
这里实际的异常已经被一大堆聚合异常层(6 个嵌套层)包裹起来。我明白为什么我会得到一个聚合异常,但想知道为什么会有这么多异常?更重要的是,因为在异常冒泡回到控制器入口点之前我正在查看异常。
这是否是多层异步等待的结果(我认为我没有多达 6 层)还是 EF7 实现中的问题?
目前使用的是 EF 7 版本 7.0.0-beta4。
正如 the MSDN page on Task<T>
所解释的那样,Task
抛出的所有异常在被抛出到等待代码之前都包含在 AggregateException
中。如果您使用多个 async/await 级别并且没有在尽可能低的级别捕获此异常,那么每次它冒泡到另一个级别时,它都会再次包装,导致 AggregateException
在 AggregateException
, 每次等待没抓到一个.
也可能是每个操作都算作自己的任务; 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
六层事物,每一层都在等待上一层的结果。六 AggregateException
层。现在,您的异常是由六个中的第三个引起的,但从错误的性质来看,它很可能来自 EF 在执行任何查询之前读取您的整个查询的部分,并且在这样做时发现您'我有一个 .Skip()
没有匹配的 .OrderBy()
。
正如 Stephen Cleary 在评论中提醒我的那样,虽然你 await
return 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