2013-06-03 80 views
7

Trong khi giả định của tôi có vẻ có vẻ chủ quan, sau một số nghiên cứu, tôi thấy rằng không có gì lạ khi tìm các nhà phát triển ủng hộ giả Try/Catch thay vì sử dụng Using statement để xử lý IDbConnection/IDbTransaction (Đóng/Cam kết/Rollback).Sử dụng IDbConnection/IDbTransaction có an toàn để sử dụng không?

Điều này đúng với một số nhà phát triển dày dạn nhất và một số nhà phát triển mới. Tôi cố ý không tham khảo bất kỳ câu hỏi nào trên StackOverflow hoặc các liên kết diễn đàn như một ví dụ, vì vậy mọi người không bị xúc phạm. Từ số what I found, tuyên bố Usingsafe to use (không có ý định chơi chữ).

Có gì sai với nó không? Xét đoạn mã sau:

Public Sub Commit() 
    Dim cn As IDbConnection = {CREATE_CONNECTION} 
    Dim tran As IDbTransaction = Nothing 

    cn.Open() 
    Try 
    tran = cn.BeginTransaction 
    'run some queries here 
    tran.Commit() 
    Catch ex As Exception 
    If Not tran Is Nothing Then tran.Rollback() 
    Throw 
    Finally 
    cn.Close() 
    End Try 
End Function 

Giả {CREATE_CONNECTION} là giữ chỗ cho một Sub tạo ra một kết nối, tùy thuộc vào nhà cung cấp cơ sở dữ liệu, được viết theo tất cả các thông lệ tốt nhất có thể và không cần phải cải thiện nhiều hơn nữa.

Có một lý do tại sao đoạn code trên không thể được viết lại như vậy:

Using cn As IDbConnection = {CREATE_CONNECTION} 
    cn.Open() 
    Using tran As IDbTransaction = cn.BeginTransaction 
    'run some queries here 
    tran.Commit() 
    End Using 
End Using 

?

Rõ ràng, phiên bản # 2 trực quan hơn với những gì nó đang làm. Nhưng có lẽ tôi đang thiếu một cái gì đó quan trọng ở đây? Những điều như triển khai cụ thể cho nhà cung cấp thư viện truy cập dữ liệu, không gọi số Transaction.Commit và/hoặc Connection.Close trên Dispose nội bộ? Phương pháp này có bị ngừng hoạt động trong tương lai gần hay không được coi là đủ rõ ràng trong mô hình lập trình hiện đại/thực tiễn tốt nhất? Công cụ dành cho nhà phát triển ứng dụng di động/đơn lẻ thiếu hỗ trợ gỡ lỗi cho từ khóa Using?

Tôi đang tìm bất kỳ loại câu trả lời nào để hỗ trợ hoặc từ chối điểm. Tốt hơn là một báo giá với tài liệu gốc, giống như Do not use Using with IDbTransaction when .... Các liên kết đến blog hoặc trải nghiệm cá nhân cũng không sao.

Trả lời

14

Tôi hoàn toàn kết nối với bạn; phải là using và không cần phải rõ ràng Close(). Giao dịch hơi phức tạp hơn một chút; mã hiển thị chắc chắn là quá mức cần thiết vào lúc này, nhưng nó không hoàn toàn được xác định rằng Dispose() nên thực hiện khôi phục. Trên thực tế, điều đó có nghĩa là điều gì có xu hướng xảy ra trong mọi triển khai mà tôi đã xem xét, nhưng hơi khó hiểu rằng ngay cả DbTransaction (mà hầu hết các nhà cung cấp sử dụng) thực sự không thực hiện việc này. Tương phản với TransactionScope nơi nó được xác định rõ ràng rằng một Dispose() mà không có cam kết được tính là một rollback. Vì lý do đó, tôi có xu hướng sử dụng (xin lỗi C#):

using(var conn = GetOpenConnection()) 
using(var tran = conn.BeginTransaction()) { 
    try { 
     // TODO: do work 
     tran.Commit(); 
    } catch { 
     tran.Rollback(); 
     throw; 
    } 
} 

đó là nơi nào đó giữa hai về độ phức tạp. Nó không phải là rối tung xung quanh với null -kiểm tra, ít nhất.

+0

Điều đó giải thích, cảm ơn. Chắc chắn rõ ràng hơn phiên bản # 1 của tôi. Ngoài ra +1 cho 'GetOpenConnection', tôi cũng đang hướng tới việc kết hợp' cn.Open() 'vào một số' CreateAndOpenConnection', vì nó có vẻ dư thừa để gọi mỗi lần. – Neolisk

+0

Nếu kết nối với cơ sở dữ liệu bị đóng, giao dịch vẫn được khôi phục? Tôi hiểu bạn lo lắng hơn về việc khóa có thể. –

11

Những gì bạn thấy là các nhà phát triển mã hóa theo tài liệu ("Điều tốt"). Các DbTransaction lớp cơ sở (được sử dụng cho việc triển khai giao dịch hầu hết các nhà cung cấp dữ liệu) nêu rõ trong its documentation:

Vứt bỏ nên rollback giao dịch.Tuy nhiên, hành vi của Vứt bỏ là nhà cung cấp cụ thể, và không nên thay thế gọi Rollback.

+3

nắm bắt tốt tài liệu –

+0

+1. Cảm ơn vì đã tìm một ghi chú chính thức về điều đó. – Neolisk

+1

Cảm ơn. MS chắc chắn sẽ làm cho nó rõ ràng hơn trên giao diện thực tế. –