使用 Dapper QueryAsync return 单个对象
Using Dapper QueryAsync to return a single object
不幸的是,我们的数据库可以追溯到 90 年代。它的遗产是如此强大,以至于我们仍在使用 SP 来完成大部分的 CRUD 操作。不过Dapper好像挺适合的,刚开始玩
但是,我有点担心如何处理单个数据行。在这种情况下,我使用 QueryAsync 来调用传递 ID 的 SP。如您所见,对象在异步调用之外返回(*)。
我会遇到麻烦吗?如果是这样,有谁知道如何处理它?我需要改用 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;
}
...
}
(*)FirstOfDefault() 返回的 SchemePolicy 对象不是异步方法。
首先,我认为您不需要 null check
,Dapper 将 return 零行用于查询。请注意,TRUE 对于 SQL Server
但是 对于任何其他 RDBMS 应该是相同的。所以这个
return schemePolicy != null ? schemePolicy.FirstOrDefault() : null;
可以简单写成
return schemePolicy.FirstOrDefault();
现在要解决真正的问题,您提到:
the object is returning outside of the async call(*)
事实并非如此。如果您以任何一种方式编写它,您将 ONLY 在查询具有 运行 之后获得您的对象。因此,以下两组代码会产生相同的行为:
var schemePolicy = await sql.QueryAsync<SchemePolicy>("sp", {rest of code});
return schemePolicy.FirstOrDefault();
和
var schemePolicy = sql.QueryAsync<SchemePolicy>("sp", {rest of code});
return schemePolicy.Result.FirstOrDefault();
现在真正关心的是您调用 GetById
的方式,以确保 (1) 该方法不会阻塞任何其他线程并且 (2) 仅当查询完成 运行ning 时,您才会获得 目标对象 。这是控制台应用程序的片段,您可以使用它进行测试:
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();
}
该测试将向您展示随后调用 GetById
方法的 GetValue
不会阻止其余代码。此外,在处理查询之前,return不会从 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();
}
Dapper现在支持QueryFirstOrDefaultAsync()
,所以你可以这样写代码,
public async Task<SchemePolicy> GetById(string id)
{
return await sql.QueryFirstOrDefaultAsync<SchemePolicy>("risk.iE_GetSchemePolicyById",
new { Id = id },
commandType: CommandType.StoredProcedure);
}
不幸的是,我们的数据库可以追溯到 90 年代。它的遗产是如此强大,以至于我们仍在使用 SP 来完成大部分的 CRUD 操作。不过Dapper好像挺适合的,刚开始玩
但是,我有点担心如何处理单个数据行。在这种情况下,我使用 QueryAsync 来调用传递 ID 的 SP。如您所见,对象在异步调用之外返回(*)。
我会遇到麻烦吗?如果是这样,有谁知道如何处理它?我需要改用 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;
}
...
}
(*)FirstOfDefault() 返回的 SchemePolicy 对象不是异步方法。
首先,我认为您不需要 null check
,Dapper 将 return 零行用于查询。请注意,TRUE 对于 SQL Server
但是 对于任何其他 RDBMS 应该是相同的。所以这个
return schemePolicy != null ? schemePolicy.FirstOrDefault() : null;
可以简单写成
return schemePolicy.FirstOrDefault();
现在要解决真正的问题,您提到:
the object is returning outside of the async call(*)
事实并非如此。如果您以任何一种方式编写它,您将 ONLY 在查询具有 运行 之后获得您的对象。因此,以下两组代码会产生相同的行为:
var schemePolicy = await sql.QueryAsync<SchemePolicy>("sp", {rest of code});
return schemePolicy.FirstOrDefault();
和
var schemePolicy = sql.QueryAsync<SchemePolicy>("sp", {rest of code});
return schemePolicy.Result.FirstOrDefault();
现在真正关心的是您调用 GetById
的方式,以确保 (1) 该方法不会阻塞任何其他线程并且 (2) 仅当查询完成 运行ning 时,您才会获得 目标对象 。这是控制台应用程序的片段,您可以使用它进行测试:
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();
}
该测试将向您展示随后调用 GetById
方法的 GetValue
不会阻止其余代码。此外,在处理查询之前,return不会从 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();
}
Dapper现在支持QueryFirstOrDefaultAsync()
,所以你可以这样写代码,
public async Task<SchemePolicy> GetById(string id)
{
return await sql.QueryFirstOrDefaultAsync<SchemePolicy>("risk.iE_GetSchemePolicyById",
new { Id = id },
commandType: CommandType.StoredProcedure);
}