2015-07-06 67 views
6

不幸的是,我们的DB可追溯到90年代。它的传统非常强大,我们仍然在使用SP来完成大部分CRUD操作。但是,看起来Dapper很适合,我们刚刚开始玩。使用Dapper QueryAsync返回单个对象

但是,我有点担心如何处理单个数据行。在这种情况下,我使用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对象不是异步方法。

+1

*正如你所看到的,对象是没有退出异步调用。*这是什么意思?你的意思是你的查询不起作用? –

+1

存储过程没有任何问题,它们就像重量较慢的ORM所产生的一样。 – Crowcoder

+0

谢谢@YuvalItzchakov,我更新了帖子 –

回答

9

首先,我不认为你需要null check,Dapper将返回零行查询。请注意,这是TRUE对于SQL Server应该是任何其他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(); 
}