Reputation: 1876
I am new to using await/async and I have a basic question. I was able to successfully implement the await/async model in my WebApi Controller and the Business Object (BL) for deletes so in the BL on the Delete
method I invoke await entities.SaveChangesAsync();
and updated the method's signature to return public static async Task<ProfileItem> Delete(int profileId, int profileItemId)
and this works!!!
Now, I want to do the same when I "fetch" data, so, I have a "getter" and I update the method's signature to public static async Task<List<Property>> GetProperties(int userId, int userTypeId)
and here I have some logic that (1) uses the entity framework to retrieve a result set, then I do some stuff and convert my EntityObject into a BusinessObject and return a List<Property>
, however when I do return await ...
I get the error: List does not contain a definition for 'GetAwaiter' and no extension method ...
Here's the code
public static async Task<List<Property>> GetProperties(int userId, int userTypeId)
{
entities = new MyEntities();
var userType = entities.sl_USER_TYPE.Where(_userType => _userType.ID == userTypeId).First();
var properties = entities.sl_PROPERTY.Where(_property => _property.USER_ID == userId && _property.USER_TYPE_ID == userTypeId);
if (!properties.Any())
throw new Exception("Error: No Properties exist for this user!");
// here is where I get the error
return await ConvertEntiesToBusinessObj(properties.ToList(), userId);
}
What do I need to do to be able to access the benefits of this functionality in this case. Basically I can use Task/async for Saving information to the DB but not getting. I am sure it is my lack of understanding.
Thanks.
Upvotes: 0
Views: 1457
Reputation: 457402
You can only use await
on "awaitables", which for the most part means Task
or Task<T>
.
ConvertEntiesToBusinessObj
does not return Task<T>
, which is fine. It sounds like a synchronous method, so it shouldn't.
What you want to do is use ToListAsync
instead of ToList
, and await
that:
return ConvertEntiesToBusinessObj(await properties.ToListAsync(), userId);
Also, as PetSerAI pointed out, it would be more efficient to use ToListAsync
once, rather than Any
followed by ToList
/ToListAsync
:
public static async Task<List<Property>> GetProperties(int userId, int userTypeId)
{
entities = new MyEntities();
var userType = await entities.sl_USER_TYPE.Where(_userType => _userType.ID == userTypeId).FirstAsync();
var properties = await entities.sl_PROPERTY.Where(_property => _property.USER_ID == userId && _property.USER_TYPE_ID == userTypeId).ToListAsync();
if (!properties.Any())
throw new Exception("Error: No Properties exist for this user!");
return ConvertEntiesToBusinessObj(properties, userId);
}
The general rule to follow here is to not approach async
with the mindset of "I want to make this function async; how do I do this?". The appropriate approach is to first identify naturally-asynchronous operations (generally I/O-based) - in this example, the EF queries. Then make those asynchronous and call them with await
, and allow async
/await
to grow naturally from there.
Upvotes: 3