Multi-asincrono in Entity Framework 6?


87

Questo è il mio codice:

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

Ma quando ho chiamato la funzione dal controller. Ha mostrato un errore

Una seconda operazione è iniziata in questo contesto prima del completamento di una precedente operazione asincrona. Usa "await" per assicurarti che tutte le operazioni asincrone siano state completate prima di chiamare un altro metodo in questo contesto. Non è garantito che tutti i membri dell'istanza siano thread-safe.

Per favore aiutami a risolvere questo problema.


Ho 2 compiti. Se eseguo ogni attività. è successo. ma se corro come il mio codice sopra. È un errore
un Hv

Risposte:


119

L'eccezione spiega chiaramente che è consentita una sola operazione asincrona per contesto alla volta.

Quindi, devi awaituno alla volta come suggerisce il messaggio di errore:

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

Oppure puoi utilizzare più contesti:

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

33
solo una nota, se hai una variabile Lazy che utilizza il contesto nella query anche con l'attesa genererà lo stesso errore, basta ottenere la proprietà prima della query, è stato un dolore scoprirlo.
Pedro.The.Kid

7
@ Pedro.The.Kid: come regola generale, non utilizzare il caricamento lento con accesso asincrono al database. Il caricamento lento è sempre sincrono, quindi è molto meglio usare Includi o separare le query per i dati aggiuntivi.
Stephen Cleary

1
C'è qualche motivo specifico per cui hai bisogno di un contesto per query asincrona? Sento che questo diventa un fattore limitante.
Zapnologica

1
@Zapnologica: è solo il modo in cui è stato progettato ES6. Ogni contesto può gestire solo una query alla volta . Quindi, se finisci una query prima dell'inizio di quella successiva, avresti bisogno di un solo contesto. È solo un problema se desideri eseguire più query contemporaneamente.
Stephen Cleary

@StephenCleary, ho difficoltà a trovare quella query perché non c'è nulla immediatamente prima dell'eccezione. C'è un modo per noi di trovare ciò che è attualmente in esecuzione? Grazie
Fabio Milheiro


3

Se utilizzi Unity per l'inserimento delle dipendenze con, ad esempio, il modello di repository, otterrai il seguente errore utilizzando due o più contesti con crea / aggiorna / elimina:

La relazione tra i due oggetti non può essere definita perché sono collegati a diversi oggetti ObjectContext.

Questo può essere risolto usando PerRequestLifetimeManager. Maggiori informazioni qui:

C # EF6 effettua più chiamate asincrone a un contesto usando Unity - Asp.Net Web Api

container.RegisterType<DbContext>(new PerRequestLifetimeManager());
container.RegisterType<ISupplierRepository, SupplierRepository>();
container.RegisterType<IContactRepository, ContactRepository>();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.