10

IAsyncEnumerable<> を返す async/await メソッドを使用して、SQL Server データベースから行を取得し、Web API .Net Core 3.0 インターフェイス経由で提供しています。8192 行を超えるまで問題なく動作します。そのポイントを超える行では失敗します。それぞれ行サイズが大きく異なる 3 つの異なるテーブルを試しました。8192行を生成した後に障害が発生するたびに。これが私が見るエラーです:

An unhandled exception occurred while processing the request.
InvalidOperationException: 'AsyncEnumerableReader' reached the configured maximum size of the buffer when enumerating a value of type 'Microsoft.EntityFrameworkCore.TestDatabase.TestDatabaseDbSet`1[TestNamespace.TestClass]'. This limit is in place to prevent infinite streams of 'IAsyncEnumerable<>' from continuing indefinitely. If this is not a programming mistake, consider ways to reduce the collection size, or consider manually converting 'Microsoft.EntityFrameworkCore.TestDatabase.TestDatabaseDbSet`1[TestNamespace.TestClass]' into a list rather than increasing the limit.
Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadTestDatabase<T>(IAsyncEnumerable<object> value)

Stack Query Cookies Headers Routing
InvalidOperationException: 'AsyncEnumerableReader' reached the configured maximum size of the buffer when enumerating a value of type 'Microsoft.EntityFrameworkCore.TestDatabase.TestDatabaseDbSet`1[TestNamespace.TestClass]'. This limit is in place to prevent infinite streams of 'IAsyncEnumerable<>' from continuing indefinitely. If this is not a programming mistake, consider ways to reduce the collection size, or consider manually converting 'Microsoft.EntityFrameworkCore.TestDatabase.TestDatabaseDbSet`1[TestNamespace.TestClass]' into a list rather than increasing the limit.
Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadTestDatabase<T>(IAsyncEnumerable<object> value)
Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadTestDatabase<T>(IAsyncEnumerable<object> value)
Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncEnumerable(ActionContext context, ObjectResult result, IAsyncEnumerable<object> asyncEnumerable)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|27_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Show raw exception details
System.InvalidOperationException: 'AsyncEnumerableReader' reached the configured maximum size of the buffer when enumerating a value of type 'Microsoft.EntityFrameworkCore.TestDatabase.TestDatabaseDbSet`1[TestNamespace.TestClass]'. This limit is in place to prevent infinite streams of 'IAsyncEnumerable<>' from continuing indefinitely. If this is not a programming mistake, consider ways to reduce the collection size, or consider manually converting 'Microsoft.EntityFrameworkCore.TestDatabase.TestDatabaseDbSet`1[TestNamespace.TestClass]' into a list rather than increasing the limit.
   at Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadTestDatabase[T](IAsyncEnumerable`1 value)
   at Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadTestDatabase[T](IAsyncEnumerable`1 value)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncEnumerable(ActionContext context, ObjectResult result, IAsyncEnumerable`1 asyncEnumerable)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|27_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
reached the configured maximum size of the buffer when enumerating a value of type Microsoft.EntityFrameworkCore DbSet  This limit is in place to prevent infinite streams from continuing indefinitely. If this is not a programming mistake, consider ways to reduce the collection size, or consider manually converting Microsoft.EntityFrameworkCore DbSet  into a list rather than increasing the limit.

Microsoft.EntityFrameworkCore.DbSet AsyncEnumerable
4

4 に答える 4

17

何が起こっていますか

制限はMvcOptions.MaxIAsyncEnumerableBufferLimit プロパティから来ます:

その ObjectResultExecutor がバッファリングする IAsyncEnumerable のエントリの最大数を取得または設定します。

Value が IAsyncEnumerable のインスタンスである場合、ObjectResultExecutor は選択されたフォーマッタを呼び出す前に列挙を積極的に読み取り、同期コレクションに追加します。このプロパティは、エグゼキュータがバッファできるエントリの最大数を決定します。

(...)

デフォルトは 8192 です。

修理

私の意見では、最高から最悪まで。

A. (推奨) あまり多くのレコードを返さない

Web API からそれほど多くのレコードを返さないことをお勧めします。

ページングは​​、多数のレコードを処理する 1 つの方法です。チュートリアル: Add sorting, filtering, and pageing - ASP.NET MVC with EF Core を確認できます。

B. 制限を調整する

MvcOptions.MaxIAsyncEnumerableBufferLimit別の値に設定できます。

C. 使用しないIAsyncEnumerable

戻ることができますIEnumerable-より多くのレコードを処理できるようになります。

于 2019-11-22T03:23:32.670 に答える
0

例外メッセージと説明は、状況を完全に説明しています。(非常に大量の) 量のデータをバッファーに読み込んでいます。フレームワークは、おそらく予期しないことを行っているか、あまりにも多くの情報を照会していることを警告しています。

WEBAPI を使用しているため、WEBAPI と一般的な Web サイトの目標は応答時間を短くすることであり、8K 以上のレコードでデータを収集する必要があるため、警告を受けています。通常、これは達成されません。そうは言っても、私たちはあなたのアプリケーションの実際のユースケースを知りませんし、気にしないかもしれませんが、フレームワークはあなたが「正しいこと」をするのを助けようとしています.

経験レベルに関係なく、エラー メッセージを読んだり解釈したりしないことは、陥りやすい罠です。代わりに、それらの意味を考えてください。理解できない場合は、理解できるまで読み直して調べてください。私たちはグルの瞑想から長い道のりを歩んできましたので、この有用な情報を当然のことと考えないでください。

TL;DR 一度に読み込んでいるデータが多すぎます。データを小さな断片にチャンクしてクライアントに返す方法を見つけます。ページ サイズを小さくすることから始めるのが最適です。

于 2019-11-22T03:33:38.843 に答える