Reputation: 820
I'm createing some methods in a standard repository class using MongoDB with c# and async methods and I've stumbled upon some strange behaviour.
In the end it's probably not strange at all, rather the problem lies in my own inexperience with async programming.
Consider this code:
public async Task<T> GetItem<T>(ObjectId id) where T : BaseItemEntity
{
var col = GetTypedCollection<T>();
var model = await col.FindAsync(x => x.Id == id);
return await model.FirstOrDefaultAsync();
}
Now that is totally fine, no compilation errors but I'm actually not sure its's correct calling await 2 times.
Now consider this code:
public async Task<T> GetItem<T>(ObjectId id) where T : BaseItemEntity
{
var col = GetTypedCollection<T>();
var model = await col.FindAsync(x => x.Id == id).FirstOrDefaultAsync();
return model;
}
Thats illegal according to the compiler. It's complaining about FirstOrDefaultAsync() not being an availble method to call. I would have to call .Result first to get access to .FirstOrDefaultAsync().
What is going on here?
Upvotes: 2
Views: 377
Reputation: 6220
var model = await col.FindAsync(x => x.Id == id).FirstOrDefaultAsync();
Should be:
var model = await (await col.FindAsync(x => x.Id == id)).FirstOrDefaultAsync();
This is because FindAsync returns a Task object, which FirstOrDefaultAsync doesn't work for. Awaiting the operation yields the actual result.
This is one of the most annoying things with async/await IMO, as it requires parentheses or variables to hold the awaited result for further processing.
Upvotes: 3
Reputation: 131
I think it actually should be
var model = await (await col.FindAsync(x => x.Id == id)).FirstOrDefaultAsync();
both Async methods return a Task object, and Tasks don't have FirstOrDefault() method( this is why await in () is required). The other one is needed because this way model is your object and not a Task.
Upvotes: 1