Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I remove async/await in repository methods if I'm just returning a Task?

I am an intern who is working on a service - repo pattern. I have read an article by Kevin Gosse. It says,

Avoid async when possible

Out of habit/muscle memory, you might write:

public async Task CallAsync()
{     
    var client = new Client();     
    return await client.GetAsync(); 
}

While the code is semantically correct, using the async keyword is not needed here and can have a significant overhead in hot paths. Try removing it whenever possible:

public Task CallAsync()
{     
   var client = new Client();     
   return client.GetAsync();    
}

However, keep in mind that you can’t use that optimization when your code is wrapped in blocks (like try/catch or using) :

public async Task Correct()
{     
   using (var client = new Client())
   {         
      return await client.GetAsync();   
   }    
}    
public Task Incorrect()    
{     
   using (var client = new Client())   
   {         
       return client.GetAsync();    // ❌ May dispose client before completion
   }   
}

In the incorrect version, since the task isn’t awaited inside of the using block, the client might be disposed before the GetAsync call completes.


My Question:

Does this optimization apply to EF Core Operations? After reading the article, I refactored my code to remove unnecessary async/await in the repository layer.

Here’s what I did:

In Service Layer (No change):

public async Task<Result<List<User>>> GetUsers()
{     
   var users = await _userRepository.GetAllAsync(); 
   if(!users.Success)
        return Result<List<User>>>.Fail("Cannot fetch users");
     return Result<List<User>>>.Success(users);
}

Then inside the repository,

Before

public async Task<List<User>> GetAllAsync()
{    
    var userList = await _context.Users.ToListAsync();
    return userList;
}

After

public Task<List<User>> GetAllAsync()
{    
    var userList = _context.Users.ToListAsync();
    return userList;
}

I don't know whether its good or bad. I just read that article and can't find the answer for myself (Due to my limited knowledge). I would like to hear an answer to understand it properly.

like image 582
Guhan Srinivasan Avatar asked Oct 11 '25 12:10

Guhan Srinivasan


1 Answers

In the context of going through EF, presumably to an out-of-process database:

It doesn't matter

This level of micro-optimozation is highly relevant for tight-loop CPU operations, but any impact here will be dwarfed by the EF, query generation, ADO.NET, sockets, routers, server IO (inbound) query parsing, query execution, data buffering, server IO (outbound), sockets, routers, more sockets, client IO, deframing, more ADO.NET, and finally result handling.

Given all that lot: an extra state machine really isn't going to matter much.

If you're writing a data layer tool (like EF, Dapper, etc), then sure: it makes sense to care, because the effort is going to be reused. But if you're an application developer:

Write the most obviously correct and maintainable version, and move on with your day. That probably means "keep the await", at least until you have an actual reason to do otherwise.

like image 154
Marc Gravell Avatar answered Oct 14 '25 01:10

Marc Gravell