2013-04-18 11 views
5

Hãy xem xét các phương pháp sau đây.TransactionScope có được áp dụng hoàn toàn cho đến khi hoàn thành một cách rõ ràng không?

DoA() 
{ 
    using (TransactionScope scope = new TransactionScope) 
    { 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     connection.Open(); 
     SqlCommand command = new SqlCommand(query, connection); 
     command.ExecuteNonReader(); 

     DoB();  

     scope.Complete(); 
    } 
    } 
} 

DoB() 
{ 
    using (TransactionScope scope = new TransactionScope) 
    { 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     connection.Open(); 
     SqlCommand command = new SqlCommand(query, connection); 
     command.ExecuteNonReader(); 

     DoC(); 

     scope.Complete(); 
    } 
    } 
} 

DoC() 
{ 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
    connection.Open(); 
    SqlCommand command = new SqlCommand(query, connection); 
    command.ExecuteNonReader(); 
    } 
} 

Nếu chúng ta gọi là DoA(), thực hiện các tương tác tiếp theo trong DoB()DoC() chạy trong bối cảnh giao dịch DoA() 's vì nó gắn liền với SQL Server? DoC() có chạy trong ngữ cảnh của cả giao dịch của DoA()DoB()?

(Hay tôi hiển nhiên hiểu lầm gì đó?)

+1

Bạn nhận giao dịch lồng nhau :) – DaveShaw

+0

Có các tùy chọn kiểm soát điều này. Xem "Quản lý luồng giao dịch bằng cách sử dụng TransactionScopeOption" của http://msdn.microsoft.com/en-us/library/ms172152(v=vs.85).aspx – AaronLS

+0

Lưu ý thêm về các giao dịch lồng nhau phải sử dụng cùng một mức độ cô lập theo thứ tự để tham gia vào giao dịch môi trường xung quanh. – AaronLS

Trả lời

4

Tất cả mã logic sẽ là một giao dịch duy nhất. Các phạm vi lồng nhau không nhất thiết phải tạo một giao dịch mới (trừ khi bạn sử dụng RequiresNew), do đó, nó sẽ là một giao dịch duy nhất. Bây giờ, mỗi phạm vi phải bỏ phiếu để hoàn tất giao dịch, vì vậy trong phạm vi thứ hai của bạn nếu bạn xóa Complete, sẽ khiến toàn bộ giao dịch trở lại.

DoC cũng sẽ là một phần của giao dịch; giao dịch môi trường xung quanh sẽ phát hiện kết nối mới và được tự động đăng ký.

Vui lòng đọc tất cả các chi tiết here giải thích hành vi đăng ký giao dịch môi trường xung quanh và các tùy chọn khác nhau Requires, RequiresNewSuppress.

Cũng lưu ý rằng nếu kết nối của bạn không sử dụng chuỗi kết nối CHÍNH XÁC, điều này sẽ tự động quảng bá toàn bộ giao dịch đến Giao dịch phân tán. Chỉ cần một cái gì đó để xem ra cho.

+0

+1 Thông tin tốt. Trước khi tôi chấp nhận, bạn có thể xác nhận rằng 'DoC()' được thực hiện trong 'Giao dịch' xung quanh từ' DoA() 'và/hoặc' DoB() '? (Đó là những gì tôi mong đợi * và * nghĩ * xảy ra - nhưng muốn chắc chắn.) – svidgen

+0

@svidgen Cập nhật câu trả lời của tôi. – Andy

+0

Đẹp. Cảm ơn! – svidgen

2

Sửa một cảm của Andy:

Có vẻ như một cái gì đó như thế này có thể xảy ra trên máy chủ SQL:

BEGIN TRANSACTION A 

    -- do A's work 

    -- B does NOT create a new transaction 

    -- do B's work 

    -- do C's work 

COMMIT TRANSACTION A 

Sau đây xảy ra nếu new TransactionScope(TransactionScopeOption.RequiresNew) được sử dụng trong DoB().

BEGIN TRANSACTION A 

    -- do A's work 

    BEING TRANSACTION B 

    -- do B's work 

    -- do C's work 

    COMMIT TRANSACTION B 
COMMIT TRANSACTION A 
+0

Đó không phải là điều sẽ xảy ra; nó sẽ là một giao dịch đơn lẻ vì phạm vi được sử dụng trong B sẽ tham gia vào giao dịch môi trường hiện tại. Nếu B không bỏ phiếu cho 'Hoàn thành' toàn bộ giao dịch sẽ quay trở lại. – Andy

+0

@Andy Cảm ơn bạn đã làm rõ. Đây có phải là những gì sẽ xảy ra nếu 'mới TransactionScope (TransactionScopeOptions.RequiresNew)' được sử dụng để thay thế? – svidgen

+0

@Andy Nevermind, vừa xem câu trả lời của bạn! – svidgen