简体   繁体   中英

C# GetAwaiter async Task<T>

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM