2014-08-28 16 views
10

Tôi đang sử dụng Dapper 1.31 từ Nuget. Tôi có đoạn mã này rất đơn giản,mã thông báo hủy trên Dapper

string connString = ""; 
string query = ""; 
int val = 0; 
CancellationTokenSource tokenSource = new CancellationTokenSource(); 
using (IDbConnection conn = new SqlConnection(connString)) 
{ 
    conn.Open(); 
    val = (await conn.QueryAsync<int>(query, tokenSource.Token)).FirstOrDefault(); 
} 

Khi tôi bấm F12 trên QueryAsync, nó trỏ tôi để

public static Task<IEnumerable<T>> QueryAsync<T> 
    (
     this IDbConnection cnn, 
     string sql, 
     dynamic param = null, 
     IDbTransaction transaction = null, 
     int? commandTimeout = null, 
     CommandType? commandType = null 
    ); 

Không có CancellationToken trên chữ ký của mình.

Câu hỏi:

  • Tại sao đoạn hoàn toàn thể xây dựng giả rằng có được không có lỗi biên dịch trên toàn bộ giải pháp?
  • Hãy tha thứ cho tôi vì tôi không thể kiểm tra nếu gọi tokenSource.Cancel() thực sự sẽ hủy phương thức vì tôi không biết cách tạo truy vấn sql đang chạy dài. Liệu các .Cancel() thực sự hủy bỏ phương pháp và ném OperationCancelledException?

Cảm ơn bạn!

+0

'param' động sẽ mất khá nhiều bất cứ điều gì. Những gì bạn đang làm giống như truyền mã thông báo hủy như một tham số cho 'Console.WriteLine (chuỗi, tham số params [])'. Chỉ vì bạn có thể vượt qua nó không có nghĩa là chức năng hỗ trợ hủy bỏ. –

Trả lời

19

Bạn đang chuyển mã thông báo hủy làm đối tượng tham số; điều đó sẽ không hoạt động.

Phương thức async đầu tiên trong công cụ lập bản đồ không hiển thị mã thông báo hủy; khi tôi cố gắng thêm chúng như là một tham số tùy chọn (như một quá tải riêng biệt, để tránh phá vỡ các assembly hiện có), things got very confused with "ambiguous method" compilation problems. Do đó, tôi phải vạch trần điều này thông qua một API riêng biệt; nhập CommandDefinition:

val = (await conn.QueryAsync<int>(
    new CommandDefinition(query, cancellationToken: tokenSource.Token) 
).FirstOrDefault(); 

Điều này sau đó chuyển mã thông báo hủy xuống tất cả các địa điểm dự kiến; đó là công việc của nhà cung cấp ADO.NET để thực sự sử dụng nó, nhưng; nó dường như hoạt động trong hầu hết các trường hợp. Lưu ý rằng nó có thể dẫn đến một SqlException thay vì một OperationCancelledException nếu hoạt động đang diễn ra; điều này một lần nữa là xuống đến các nhà cung cấp ADO.NET, nhưng làm cho rất nhiều ý nghĩa: bạn có thể đã bị gián đoạn một cái gì đó quan trọng; nó bề mặt như một vấn đề kết nối quan trọng.

Đối với các câu hỏi sau:

Tại sao đoạn hoàn toàn thể xây dựng giả định rằng không có lỗi biên dịch trên toàn bộ giải pháp?

Vì ... nó hợp lệ C#, ngay cả khi nó không làm những gì bạn mong đợi.

Tha thứ cho tôi vì tôi không thể kiểm tra nếu gọi tokenSource.Cancel() thực sự sẽ hủy phương thức vì tôi không biết cách tạo truy vấn sql đang chạy dài. Liệu .Cancel() có thực sự hủy bỏ phương thức và ném ra OperationCancelledException không?

Nhà cung cấp ADO.NET cụ thể, nhưng có nó thường hoạt động. Ví dụ về "cách tạo truy vấn sql đang chạy dài"; lệnh waitfor delay trên máy chủ SQL có phần hữu ích ở đây và là những gì tôi sử dụng trong các bài kiểm tra tích hợp.

+1

Đây là câu trả lời hay từ chính tác giả. Cảm ơn Marc về API thay thế! Vâng, tôi tốt với việc bắt 'SqlException' thay vì' OperationCancelledException', tôi sẽ xử lý logic ở đây. Cảm ơn một lần nữa! – Pedigree

+1

@Pedigree I * nghĩ * Tôi cũng đã tìm ra cách làm cho nó hoạt động chính xác trong API chính. –

+0

Tôi có một câu hỏi khác marc và tôi không biết nếu điều này vẫn còn trong phạm vi, tại sao bạn đã đặt '.ConfigureAwait (false)' trên * dòng 78 * của [tệp: SqlMapperAsync.cs] (https: // github.com/StackExchange/dapper-dot-net/blob/master/Dapper%20NET45/SqlMapperAsync.cs)? Điều đó thực sự có ý nghĩa gì? Cảm ơn. – Pedigree

1

Bạn có thể sửa SqlMapper.cs trong Dapper lib bằng cách thêm những dòng này:

internal IDbCommand SetupCommand(IDbConnection cnn, Action<IDbCommand, object> paramReader) 
    { 
     var cmd = cnn.CreateCommand(); 

#if ASYNC 
     // We will cancel our IDbCommand 
     CancellationToken.Register(() => cmd.Cancel()); 
#endif 

Rebuild lib Dapper riêng của bạn và thưởng thức :)

Các vấn đề liên quan