2015-07-06 97 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(); 
}