Reputation: 5747
Yes, I know there are other questions to cover what this warning means and how to solve it, however, I have a question about best practices regarding async programming.
I have a service layer which handles data transfer between the data layer and the presentation layer. This service contains several methods which query the database, and return the result.
I have been trying to use async programming wherever possible. An example:
public async Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)
{
return await Database.FindBy<SiteTemplateResource>(str => str.SiteTemplateId == siteTemplateId && str.HashedFile.EndsWith(extension)).ToArrayAsync();
}
My problem with this is, I'm not actually awaiting anything, other than to the ToArrayAsync
call, which I don't really need.
Should I go ahead and use async/await for this? And how would I for example await anything for this function:
public async Task<int> SiteTemplateBySiteIdAsync(int siteId)
{
return Database.First<SiteSiteTemplate>(sst => sst.SiteId == siteId).SiteTemplateId;
}
I don't await anything in that function, but I also don't need to call ToArrayAsync
, so how do I avoid the warning "method lacks 'await' operator" in above case?
Thanks in advance.
Upvotes: 3
Views: 250
Reputation: 131237
async/await
are needed only if you want to process the results of an already asynchronous operation in the method itself. They don't make the method or the call asynchronous. If you don't need to process the Task result, you can just return it:
public Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)
{
return Database.FindBy<SiteTemplateResource>(str =>
str.SiteTemplateId == siteTemplateId
&& str.HashedFile.EndsWith(extension))
.ToArrayAsync();
}
or, using an expression bodied method
public Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)=>
Database.FindBy<SiteTemplateResource>(str =>
str.SiteTemplateId == siteTemplateId
&& str.HashedFile.EndsWith(extension))
.ToArrayAsync();
You can avoid async/await
in the second case as well and still keep it asynchronous, if you use Where
,Select and FirstAsync
:
public Task<int> SiteTemplateBySiteIdAsync(int siteId)=>
Database.Where(sst => sst.SiteId == siteId)
.Select(it=>it.SiteTemplateId)
.FirstAsync();
}
This has the added advantage of returning only the ID from the database. If you didn't use Select
, the provider would have to read the entire object
Upvotes: 1
Reputation: 101453
Asynchornous api does not necessary need async\await keywords. First you should ask yourself if anything you call inside your method use IO and have asynchronous version of that IO api. In your case you try to access database, that is IO, your library has asynchronous version (ToArrayAsync
), so all makes sense. Now check if you do anything else after calling that asynchronous api. If yes - use async\await. If not - just return the result back to the caller:
public Task<SiteTemplateResource[]> GetResources(int siteTemplateId, string extension)
{
return Database.FindBy<SiteTemplateResource>(str => str.SiteTemplateId == siteTemplateId && str.HashedFile.EndsWith(extension)).ToArrayAsync();
}
In the second case you also try to access database, but you think that there is no async api to do that. Most likely that is not true, because if you have ToArrayAsync
- it's very likely all database access methods have async version and so you should have FirstAsync
. Then your method becomes:
public async Task<int> SiteTemplateBySiteIdAsync(int siteId)
{
var result = await Database.FirstAsync<SiteSiteTemplate>(sst => sst.SiteId == siteId);
return result.SiteTemplateId;
}
Here you do something after calling FirstAsync
, so you need to use async\await keywords.
Upvotes: 2
Reputation: 156948
If you have nothing to await
in a method that needs to be async
(for whatever reason), you can use Task.FromResult
, which can be awaited:
public async Task<int> SiteTemplateBySiteIdAsync(int siteId)
{
return await Task.FromResult(Database.First<SiteSiteTemplate>(sst => sst.SiteId == siteId).SiteTemplateId);
}
If you don't need the async
method, you can simply more the async Task<int>
and replace it for int
.
Upvotes: 5
Reputation: 1
Maybe you can change your code like bellow:
public int SiteTemplateBySiteIdAsync(int siteId)
{
return Database.First<SiteSiteTemplate>(sst => sst.SiteId == siteId).SiteTemplateId;
}
Have a nice day!
Upvotes: 0