First of all, I donβt think you need a null check , Dapper will return a null string for the request. Indicate that this is TRUE for SQL Server , but must be the same for any other DBMS. So this is
return schemePolicy != null ? schemePolicy.FirstOrDefault() : null;
can be simply written as
return schemePolicy.FirstOrDefault();
Now, to solve the real problem, and you mentioned:
object returns outside of asynchronous call (*)
This is not true. If you write it anyway, you will ONLY receive your object after the request. Thus, two sets of codes give the same behavior:
var schemePolicy = await sql.QueryAsync<SchemePolicy>("sp", {rest of code}); return schemePolicy.FirstOrDefault();
and
var schemePolicy = sql.QueryAsync<SchemePolicy>("sp", {rest of code}); return schemePolicy.Result.FirstOrDefault();
Now the problem is that you are calling GetById to make sure that (1) the method will not block any other thread and (2) that you will receive the target ONLY when the request completes. Here is a snippet for a console application with which you can test it:
static async void GetValue() { var repo = new SchemePolicyRepository(new DbManager());
This test will show you that GetValue , which therefore calls the GetById method, does not block the rest of the code. In addition, nothing is returned from FirstOrDefault until the request is processed.
Here's the supporting code for the query in case someone wants to try and make sure the concept is valid (the code works with SQL Server 2008 and later):
public async Task<int> GetById() { var sql = @" WAITFOR DELAY '00:00:05'; select 1 where 1=1"; var result = await {the_open_connection}.QueryAsync<int>(sql); return result.FirstOrDefault(); }