Reputation: 2061
The following code (on a single DbContext) results in "A second operation started on this context before a previous operation completed".
[HttpGet]
[Route("api/[controller]/circuit")]
public async Task<IEnumerable<object>> GetAllCircuits()
{
var circuits = await Task.WhenAll((await _context.Circuits.ToListAsync()).Select(async x => new
{
x.Id,
x.FastestLap,
x.LengthInMiles,
Country = await _context.Countries.FirstOrDefaultAsync(c => c.Id == x.CountryId),
Map = await _context.Maps.FirstOrDefaultAsync(m => m.Id == x.MapId),
Locations = await _context.Locations.Where(l => l.CircuitId == x.Id).ToListAsync()
}));
return circuits;
}
I was able to fix this by stripping out the async/await
and Task.WhenAll
parts, and replacing them with .Result
, which seems to be a big no-no in .NET. Fixed example below:
[HttpGet]
[Route("api/[controller]/circuit")]
public async Task<IEnumerable<object>> GetAllCircuits()
{
var circuits = (await _context.Circuits.ToListAsync()).Select(x => new
{
x.Id,
x.FastestLap,
x.LengthInMiles,
Country = _context.Countries.FirstOrDefaultAsync(c => c.Id == x.CountryId).Result,
Map = _context.Maps.FirstOrDefaultAsync(m => m.Id == x.MapId).Result,
Locations = _context.Locations.Where(l => l.CircuitId == x.Id).ToListAsync().Result
});
return circuits;
}
My three questions are:
.ToList()
rather than the async variant?Thanks!
Upvotes: 0
Views: 116
Reputation: 457147
Why does this happen?
DbContext
doesn't allow multiple operations on the same db connection. In this case, you have one call (ToListAsync
) followed by multiple concurrent calls (the Select
).
Is the "fixed" code clean? If not, please could you suggest a better approach?
No. You shouldn't use .Result
.
Your options are:
.Result
is working, but a better solution would be to use await
, just do them one at a time instead of using Select
with Task.WhenAll
. The disadvantage to this approach is that the operations are only done one at a time.Can I just use .ToList() rather than the async variant?
The ToListAsync
isn't the problem. The problem is Select
+ WhenAll
.
Upvotes: 3