Entity Framework 6のマルチ非同期?


87

これは私のコードです:

var banner = context.Banners.ToListAsync()
var newsGroup = context.NewsGroups.ToListAsync()
await Task.WhenAll(banner, newsGroup);

しかし、コントローラーから関数を呼び出したとき。エラーが表示されました

前の非同期操作が完了する前に、このコンテキストで2番目の操作が開始されました。'await'を使用して、このコンテキストで別のメソッドを呼び出す前に、非同期操作が完了したことを確認します。インスタンスメンバーは、スレッドセーフであることが保証されていません。

この問題の解決にご協力ください。


私には2つのタスクがあります。各タスクを実行した場合。それは成功です。しかし、上記のコードのように実行した場合。それはエラーです
Hv

回答:


119

例外は、コンテキストごとに一度に許可される非同期操作が1つだけであることを明確に説明しています。

したがって、awaitエラーメッセージが示すように、一度に1つずつ実行する必要があります。

var banner = await context.Banners.ToListAsync();
var newsGroup = await context.NewsGroups.ToListAsync();

または、複数のコンテキストを使用できます。

var banner = context1.Banners.ToListAsync();
var newsGroup = context2.NewsGroups.ToListAsync();
await Task.WhenAll(banner, newsGroup);

33
注意点として、待機していてもクエリでコンテキストを使用するLazy変数がある場合は、同じエラーがスローされます。クエリの前にプロパティを取得するだけです。これを見つけるのは面倒でした。
Pedro.The.Kid 2014年

7
@ Pedro.The.Kid:原則として、非同期DBアクセスで遅延読み込みを使用しないでください。遅延読み込みは常に同期しているため、追加データには包含クエリまたは個別クエリを使用することをお勧めします。
スティーブンクリアリー2014年

1
非同期クエリごとにコンテキストが必要な特定の理由はありますか?これはかなりの制限要因になると思います。
Zapnologica 2016年

1
@Zapnologica:それはES6が設計された方法です。各コンテキストは、一度に1つのクエリのみを処理できます。したがって、次のクエリが始まる前に1つのクエリを終了した場合、必要なコンテキストは1つだけです。複数のクエリを同時に実行したい場合にのみ問題になります。
スティーブンクリアリー2016年

@StephenCleary、例外の直前には何もないので、そのクエリを見つけるのに苦労しています。現在実行されているものを見つける方法はありますか?ありがとう
Fabio Milheiro 2016年


3

たとえばリポジトリパターンで依存性注入にUnityを使用する場合、create / update / deleteで2つ以上のコンテキストを使用すると次のエラーが発生します。

2つのオブジェクトは異なるObjectContextオブジェクトにアタッチされているため、2つのオブジェクト間の関係を定義できません。

これは、を使用して解決できますPerRequestLifetimeManager。詳細はこちら:

C#EF6は、Unityを使用して1つのコンテキストに対して複数の非同期呼び出しを行います-Asp.Net Web Api

container.RegisterType<DbContext>(new PerRequestLifetimeManager());
container.RegisterType<ISupplierRepository, SupplierRepository>();
container.RegisterType<IContactRepository, ContactRepository>();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.