不幸的是,我们的数据库可以追溯到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;
}
...
}
(*) FirstOfDefault()返回的SchemePolicy对象不是异步方法。
答案 0 :(得分:11)
首先,我认为你不需要null check
,Dapper将为查询返回零行。请注意,对于SQL Server
,这是 TRUE ,但对于任何其他RDBMS,应该相同。所以这个
return schemePolicy != null ? schemePolicy.FirstOrDefault() : null;
可以简单地写成
return schemePolicy.FirstOrDefault();
现在要解决真正的问题,你提到了:
对象返回异步调用(*)
之外
事实并非如此。如果您以任何一种方式编写它,您将仅在查询运行后获取您的对象。因此,以下两组代码会产生相同的行为:
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)只有在查询运行完毕后才能获得目标对象。这是一个控制台应用程序的代码段,您可以使用以下方法对其进行测试:
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();
}
该测试将向您显示因此调用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();
}
答案 1 :(得分:1)
Dapper现在支持QueryFirstOrDefaultAsync()
,因此您可以编写如下代码,
public async Task<SchemePolicy> GetById(string id)
{
return await sql.QueryFirstOrDefaultAsync<SchemePolicy>("risk.iE_GetSchemePolicyById",
new { Id = id },
commandType: CommandType.StoredProcedure);
}