Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-async in Entity Framework 6?

This is my code:

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

But when i called the function from controller. It showed error

A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.

Please help me solve this issue.

like image 676
An Hv Avatar asked Dec 17 '13 07:12

An Hv


People also ask

What does SaveChangesAsync do?

SaveChangesAsync(CancellationToken)Saves all changes made in this context to the database. This method will automatically call DetectChanges() to discover any changes to entity instances before saving to the underlying database.

What is FirstOrDefaultAsync?

FirstOrDefaultAsync<TSource>(IQueryable<TSource>) Asynchronously returns the first element of a sequence, or a default value if the sequence contains no elements.

Should I use async EF core?

Generally speaking, if there are asynchronous APIs, then you should use them for new code. Asynchronous code frees up the calling thread. If your application is a GUI application, this can free up the UI thread; if your application is a server application, this can free up threads to handle other requests.

What is AnyAsync?

AnyAsync<TSource>(IQueryable<TSource>)Asynchronously determines whether a sequence contains any elements. C# Copy.


3 Answers

The exception explains clearly that there is only one asynchronous operation per context allowed at a time.

So, you either have to await them one at a time as the error message suggests:

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

Or you can use multiple contexts:

var banner = context1.Banners.ToListAsync();
var newsGroup = context2.NewsGroups.ToListAsync();
await Task.WhenAll(banner, newsGroup);
like image 157
Stephen Cleary Avatar answered Oct 31 '22 23:10

Stephen Cleary


If you are using IoC container for your Data Provider injection, consider to use "transient" or "PerWebRequest" type for your lifecycle.

For example: https://github.com/castleproject/Windsor/blob/master/docs/lifestyles.md

like image 36
Teoman shipahi Avatar answered Oct 31 '22 22:10

Teoman shipahi


If you use Unity for dependency injection with for example repository pattern you will get the following error using two or more contexts with create/update/delete:

The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.

This can be solved using PerRequestLifetimeManager. More info here:

C# EF6 make multiple async calls to one context using Unity - Asp.Net Web Api

container.RegisterType<DbContext>(new PerRequestLifetimeManager());
container.RegisterType<ISupplierRepository, SupplierRepository>();
container.RegisterType<IContactRepository, ContactRepository>();
like image 39
Ogglas Avatar answered Nov 01 '22 00:11

Ogglas