2015-07-06 15 views
6

Rất tiếc, DB của chúng tôi có niên đại từ những năm 90. Di sản của nó là rất mạnh mẽ mà chúng tôi vẫn đang sử dụng SP để làm hầu hết các hoạt động CRUD. Tuy nhiên, có vẻ như Dapper rất hợp với nhau và chúng tôi mới bắt đầu chơi.Sử dụng Dapper QueryAsync để trả về một đối tượng đơn

Tuy nhiên, tôi hơi lo lắng về cách xử lý một hàng dữ liệu. Trong trường hợp này, tôi đang sử dụng QueryAsync để gọi SP đi qua một ID. Như bạn có thể thấy, đối tượng đang quay lại bên ngoài cuộc gọi không đồng bộ (*).

Tôi có gặp rắc rối không? Nếu vậy, có ai biết cách xử lý nó không? Tôi có cần sử dụng QuerySync không?

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; 
    } 
    ... 
} 

(*) Đối tượng SchemePolicy do FirstOfDefault() trả về không phải là phương pháp không đồng bộ.

+1

* Như bạn có thể thấy, các đối tượng là không quay trở lại cuộc gọi không đồng bộ. * Điều đó có nghĩa là gì? Bạn có nghĩa là truy vấn của bạn không hoạt động? –

+1

Không có gì sai với các thủ tục được lưu trữ, chúng là SQL giống như các ORM nặng, chậm phát sinh. – Crowcoder

+0

Cảm ơn @YuvalItzchakov, tôi đã cập nhật bài đăng –

Trả lời

9

Trước hết, tôi không nghĩ bạn cần số null check, Dapper sẽ trả về hàng không cho truy vấn. LƯU Ý rằng đây là TRUE cho SQL Servernhưng phải giống nhau đối với bất kỳ RDBMS nào khác. Vì vậy, đây

return schemePolicy != null ? schemePolicy.FirstOrDefault() : null; 

có thể chỉ cần viết như

return schemePolicy.FirstOrDefault(); 

Bây giờ để giải quyết những mối quan tâm thực sự, và bạn đề cập:

đối tượng được trở về bên ngoài của cuộc gọi async (*)

Điều đó không đúng. Nếu bạn viết nó theo cách bạn sẽ CHỈ lấy đối tượng của bạn sau khi truy vấn đã chạy. Vì vậy, sau đây sẽ hai bộ mã mang lại hành vi tương tự:

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(); 

Mối quan tâm bây giờ thực sự là với cách bạn gọi GetById để đảm bảo rằng (1) phương pháp sẽ không chặn bất kỳ chủ đề nào khác và (2) rằng bạn sẽ nhận được đối tượng đích đích CHỈ khi truy vấn đã chạy xong. Dưới đây là một đoạn mã cho một điều khiển ứng dụng mà bạn có thể thử nghiệm nó với:

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(); 
} 

Đó thử nghiệm sẽ cho bạn thấy rằng GetValue mà hậu quả là gọi GetById phương pháp không chặn phần còn lại của mã này. Ngoài ra, không có gì được trả về từ FirstOrDefault cho đến khi truy vấn được xử lý.

Dưới đây là đoạn mã hỗ trợ cho truy vấn trong trường hợp ai đó muốn thử và xác minh rằng khái niệm này là hợp lệ (mã làm việc với SQL Server 2008 và sau):

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(); 
} 
Các vấn đề liên quan