Multi-async w Entity Framework 6?

87

To jest mój kod:

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

Ale kiedy wywołałem funkcję z kontrolera. Pokazał błąd

Druga operacja rozpoczęła się w tym kontekście przed zakończeniem poprzedniej operacji asynchronicznej. Użyj „await”, aby upewnić się, że wszystkie operacje asynchroniczne zostały zakończone przed wywołaniem innej metody w tym kontekście. Żaden element członkowski instancji nie gwarantuje bezpieczeństwa wątków.

Proszę, pomóż mi rozwiązać ten problem.

An Hv
źródło
Mam 2 zadanie. Jeśli uruchomię każde zadanie. to sukces. ale jeśli uruchomię się jak mój kod powyżej. To błąd
An Hv

Odpowiedzi:

119

Wyjątek wyjaśnia wyraźnie, że w danym momencie jest tylko jedna operacja asynchroniczna na kontekst.

Więc albo musisz awaitje pojedynczo, jak sugeruje komunikat o błędzie:

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

Lub możesz użyć wielu kontekstów:

var banner = context1.Banners.ToListAsync();
var newsGroup = context2.NewsGroups.ToListAsync();
await Task.WhenAll(banner, newsGroup);
Stephen Cleary
źródło
34
uwaga, jeśli masz zmienną Lazy, która używa kontekstu w zapytaniu, nawet z await, zwróci ten sam błąd, po prostu pobierz właściwość przed zapytaniem, trudno było się tego dowiedzieć.
Pedro.The.Kid
7
@ Pedro.The.Kid: Zasadniczo nie używaj leniwego ładowania z asynchronicznym dostępem do bazy danych. Ładowanie z opóźnieniem jest zawsze synchroniczne, więc znacznie lepiej jest używać zapytań Uwzględnij lub oddzielnych zapytań dla dodatkowych danych.
Stephen Cleary
1
Czy istnieje jakiś konkretny powód, dla którego potrzebujesz kontekstu dla zapytania asynchronicznego? Wydaje mi się, że staje się to pewnym czynnikiem ograniczającym.
Zapnologica
1
@Zapnologica: Tak właśnie zaprojektowano ES6. Każdy kontekst może obsługiwać tylko jedno zapytanie naraz . Więc jeśli zakończysz jedno zapytanie przed rozpoczęciem następnego, potrzebujesz tylko jednego kontekstu. To tylko problem, jeśli chcesz wykonywać wiele zapytań w tym samym czasie.
Stephen Cleary
@StephenCleary, mam trudności ze znalezieniem tego zapytania, ponieważ nie ma nic bezpośrednio przed wyjątkiem. Czy istnieje sposób, abyśmy mogli sprawdzić, co jest obecnie wykonywane? Dzięki
Fabio Milheiro
3

Jeśli używasz Unity do iniekcji zależności z na przykład wzorcem repozytorium, otrzymasz następujący błąd przy użyciu dwóch lub więcej kontekstów z tworzeniem / aktualizowaniem / usuwaniem:

Nie można zdefiniować relacji między dwoma obiektami, ponieważ są one dołączone do różnych obiektów ObjectContext.

Można to rozwiązać za pomocą PerRequestLifetimeManager. Więcej informacji tutaj:

C # EF6 wykonaj wiele wywołań asynchronicznych do jednego kontekstu przy użyciu aparatu Unity - Asp.Net Web Api

container.RegisterType<DbContext>(new PerRequestLifetimeManager());
container.RegisterType<ISupplierRepository, SupplierRepository>();
container.RegisterType<IContactRepository, ContactRepository>();
Ogglas
źródło