許多嵌套的AggregateExceptions

aggregateexception async-await c# entity-framework-core

使用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類中。所有級別的呼叫都使用async-await。

但是我從中獲得的聚合異常是(這是從上面顯示的catch塊轉移到即時窗口):

System.AggregateException:發生一個或多個錯誤。 ---> System.AggregateException:發生一個或多個錯誤。 ---> System.AggregateException:發生一個或多個錯誤。 ---> System.AggregateException:發生一個或多個錯誤。 ---> System.AggregateException:發生一個或多個錯誤。 ---> System.AggregateException:發生一個或多個錯誤。 ---> System.InvalidOperationException:包含Skip運算符的查詢必須至少包含一個OrderBy操作。 Microsoft.Data.Entity.Relational.Query上的Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.VisitSelectExpression(SelectExpression selectExpression)中的Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.GenerateLimitOffset(SelectExpression selectExpression) .Expressions.SelectExpression.Accept(ExpressionTreeVisitor visitor)在Microsoft.Data.Entity.Relational.Query.Sql.DefaultSqlQueryGenerator.GenerateSql(SelectExpression selectExpression,IDictionary`2 parameterValues)等等

這裡實際的異常最終被一大堆聚合異常(6個嵌套層)包裹著。我理解為什麼我會得到一個總體異常,但是想知道為什麼這麼多呢?更重要的是,因為我在查看異常之前它已經回到控制器入口點。

這是多層async-await的結果,(不要認為我有多達6個)或者它可能是EF7實現中的一個問題?

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

一般承認的答案

正如Task<T>上的MSDN頁面所解釋的那樣,在拋出到等待代碼之前, Task拋出的所有異常都包含在AggregateException 。如果你使用多個級別的async / await並且沒有在盡可能低的級別捕獲此異常,那麼每次它冒泡到另一個級別時,它將再次被包裝,導致AggregateException內部出現AggregateException ,每次出現一次等待沒有抓住。

也可能是每個操作都被視為自己的任務;即。每次添加另一個操作時,結果都會從前一個操作中出現,然後返回到下一個操作中,每個操作都等待前一個操作。看一看:

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返回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




許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因