Multi-Async in Entity Framework 6?

87

Das ist mein Code:

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

Aber als ich die Funktion vom Controller aus anrief. Es zeigte Fehler

In diesem Kontext wurde eine zweite Operation gestartet, bevor eine vorherige asynchrone Operation abgeschlossen wurde. Verwenden Sie 'wait', um sicherzustellen, dass alle asynchronen Vorgänge abgeschlossen sind, bevor Sie eine andere Methode in diesem Kontext aufrufen. Es wird nicht garantiert, dass Instanzmitglieder threadsicher sind.

Bitte helfen Sie mir, dieses Problem zu lösen.

Ein Hv
quelle
Ich habe 2 Aufgaben. Wenn ich jede Aufgabe ausführe. Es ist Erfolg. aber wenn ich wie mein Code oben laufen. Es ist ein Fehler
Ein Hv

Antworten:

118

Die Ausnahme erklärt deutlich, dass jeweils nur eine asynchrone Operation pro Kontext zulässig ist.

Sie müssen awaitsie also entweder einzeln ausführen, wie in der Fehlermeldung angegeben:

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

Oder Sie können mehrere Kontexte verwenden:

var banner = context1.Banners.ToListAsync();
var newsGroup = context2.NewsGroups.ToListAsync();
await Task.WhenAll(banner, newsGroup);
Stephen Cleary
quelle
33
Nur eine Anmerkung: Wenn Sie eine Lazy-Variable haben, die den Kontext in der Abfrage verwendet, auch wenn sie abwartet, wird derselbe Fehler ausgegeben. Rufen Sie einfach die Eigenschaft vor der Abfrage ab. Es war schwierig, dies herauszufinden.
Pedro.The.Kid
7
@ Pedro.The.Kid: Verwenden Sie in der Regel kein verzögertes Laden mit asynchronem DB-Zugriff. Das verzögerte Laden ist immer synchron, daher ist es weitaus besser, Include- oder separate Abfragen für die zusätzlichen Daten zu verwenden.
Stephen Cleary
1
Gibt es einen bestimmten Grund, warum Sie einen Kontext pro asynchroner Abfrage benötigen? Ich habe das Gefühl, dass dies ein ziemlich begrenzender Faktor wird.
Zapnologica
1
@Zapnologica: Es ist genau so, wie ES6 entworfen wurde. Jeder Kontext kann nur eine Abfrage behandeln zu einer Zeit . Wenn Sie also eine Abfrage beenden, bevor die nächste beginnt, benötigen Sie nur einen Kontext. Dies ist nur dann ein Problem, wenn Sie mehrere Abfragen gleichzeitig ausführen möchten.
Stephen Cleary
@StephenCleary, es fällt mir schwer, diese Abfrage zu finden, da es unmittelbar vor der Ausnahme nichts gibt. Gibt es eine Möglichkeit für uns, herauszufinden, was gerade ausgeführt wird? Vielen Dank
Fabio Milheiro
2

Wenn Sie Unity für die Abhängigkeitsinjektion mit beispielsweise einem Repository-Muster verwenden, wird der folgende Fehler angezeigt, wenn zwei oder mehr Kontexte mit create / update / delete verwendet werden:

Die Beziehung zwischen den beiden Objekten kann nicht definiert werden, da sie an verschiedene ObjectContext-Objekte angehängt sind.

Dies kann mit gelöst werden PerRequestLifetimeManager. Mehr Infos hier:

C # EF6 führt mit Unity - Asp.Net Web Api mehrere asynchrone Aufrufe an einen Kontext aus

container.RegisterType<DbContext>(new PerRequestLifetimeManager());
container.RegisterType<ISupplierRepository, SupplierRepository>();
container.RegisterType<IContactRepository, ContactRepository>();
Ogglas
quelle