使用Dapper QueryAsync返回单个对象

Ste*_*tri 10 c# asynchronous repository dapper

不幸的是,我们的数据库可以追溯到90年代.它的遗产非常强大,我们仍在使用SP来完成大部分CRUD操作.然而,似乎Dapper很适合,我们刚刚开始玩.

但是,我有点担心如何处理单个数据行.在这种情况下,我使用QueryAsync来调用SP传递ID.如您所见,对象在异步调用(*)之外返回.

我会遇到麻烦吗?如果是这样,有谁知道如何处理它?我需要使用QuerySync吗?

public class SchemePolicyRepository : ISchemePolicyRepository
{
    private readonly SqlConnection sql;

    protected SchemePolicyRepository(SqlConnection connection)
    {
        sql = connection;
    }
    ... 
    public async Task<SchemePolicy> GetById(string id)
    {
        var schemePolicy = await sql.QueryAsync<SchemePolicy>("risk.iE_GetSchemePolicyById",
            new { Id = id },
            commandType: CommandType.StoredProcedure);
        return schemePolicy != null ? schemePolicy.FirstOrDefault() : null;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

(*)FirstOfDefault()返回的SchemePolicy对象不是异步方法.

von*_* v. 11

首先,我认为你不需要null check,Dapper会为查询返回零行.请注意,这是正确的,SQL Server 对于任何其他RDBMS应该是相同的.所以这

return schemePolicy != null ? schemePolicy.FirstOrDefault() : null;
Run Code Online (Sandbox Code Playgroud)

可以简单地写成

return schemePolicy.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

现在要解决真正的问题,你提到:

对象在异步调用之外返回(*)

事实并非如此.如果以任何一种方式编写它,您将在查询运行后获取对象.所以以下两组代码会产生相同的行为:

var schemePolicy = await sql.QueryAsync<SchemePolicy>("sp", {rest of code});
return schemePolicy.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

var schemePolicy = sql.QueryAsync<SchemePolicy>("sp", {rest of code});
return schemePolicy.Result.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

现在关注的是你调用的方式GetById,以确保(1)方法不会阻止任何其他线程,以及(2)只有在查询完成运行时才会获得目标对象.这是一个控制台应用程序的片段,您可以使用以下方法对其进行测试:

static async void GetValue()
{
    var repo = new SchemePolicyRepository(new DbManager()); // creates an open connection 
    var result = await repo.GetById();
    Console.WriteLine(result);
}

static void Main(string[] args)
{
    GetValue();   
    Console.WriteLine("Query is running...");
    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)

该测试将向您显示GetValue因此调用该GetById方法不会阻止其余代码.此外,FirstOrDefault在处理查询之前不会返回任何内容.

以下是查询的支持代码,以防有人想要尝试验证该概念是否有效(代码适用于SQL Server 2008及更高版本):

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();
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*vén 10

QueryFirstOrDefaultAsync()现在Dapper支持,所以你可以写这样的代码,

public async Task<SchemePolicy> GetById(string id)
{
    return await sql.QueryFirstOrDefaultAsync<SchemePolicy>("risk.iE_GetSchemePolicyById",
        new { Id = id },
        commandType: CommandType.StoredProcedure);
}
Run Code Online (Sandbox Code Playgroud)