2012-07-10 31 views
6

Chúng tôi đang trong quá trình thay thế dần mã truy cập dữ liệu cũ theo khung thực thể (4.3.1). Trong một số trường hợp, chúng tôi không thể tránh sử dụng cả hai cách truy cập dữ liệu trong một đơn vị công việc. Lý tưởng nhất, điều này nên được thực hiện trong một giao dịch. Tuy nhiên, mã cũ sử dụng SqlTransaction s gọi Commit() khi một đơn vị công việc được thực hiện và EF quản lý các giao dịch của riêng mình.Bỏ qua SqlTransaction.Commit trong TransactionScope

Vì vậy, chúng tôi đã nghĩ đến việc bao gồm mã "cũ" và "mới" trong một số TransactionScope. Tuy nhiên, một Commit trong một xung quanh TransactionScope luôn được thực hiện, ngay cả khi TransactionScope không được hoàn thành. Đoạn mã này minh họa vấn đề của tôi:

using (var conn = new SqlConnection("connection string")) 
{ 
    conn.Open(); 
    using (var scope = new TransactionScope()) 
    { 
    using (var tr = conn.BeginTransaction()) 
    { 
     using (var cmd = conn.CreateCommand()) 
     { 
     cmd.Transaction = tr; 
     cmd.CommandText = "some update statement"; 
     cmd.ExecuteNonQuery(); 
     } 
     tr.Commit(); 
    } 
    // In reality the code above is part of a legacy DAL, immutable. 
    // (can't insert SaveChanges before tr.Commit). 
    context.SaveChanges(); 
    if (<all ok>) // pseudo code for exception handling. 
     scope.Complete(); 
    } 
} 

Các báo cáo cập nhật vẫn cam kết khi scope.Complete() không phải là hit.

Vì vậy, có vẻ như tôi không thể sử dụng TransactionScope để buộc mã truy cập dữ liệu cũ và SaveChanges từ ngữ cảnh để thực thi trong một giao dịch. Hoặc có cách nào để ghi đè lên câu lệnh SqlTransaction.Commit?

Tôi biết rằng có nhiều bài đăng ở đây về TransactionScope và SqlTransaction, nhưng tất cả (đúng) nói rằng việc sử dụng SqlTransaction không cần thiết (cũng không được khuyến nghị) khi sử dụng TransactionScope. Nhưng không sử dụng SqlTransaction không phải là một tùy chọn ở đây. Chúng tôi có một khung kế thừa cam kết riêng của mình SqlTransaction s và không có api để móc vào cơ chế giao dịch của nó.

+0

Bạn ít nhất có quyền truy cập vào kết nối không? –

+0

@LadislavMrnka Không, ngoài chuỗi kết nối trong tệp cấu hình. –

Trả lời

7

Câu lệnh cập nhật vẫn được cam kết khi scope.Complete() không được nhấn.

Ồ không !! TransacationScope không được sử dụng .

Auto-tranh thủ chỉ công trình nếu kết nối được mở sau (hoặc bên) các TransactionScope.

Đưa Openbên các TransactionScopenên khắc phục vấn đề này (ngay cả với các giao dịch thủ công?) Như Connection sau đó sẽ [thường] tự động nhập ngũ trong bối cảnh môi trường xung quanh TS.

Kết nối hiện có có thể được đưa vào phạm vi giao dịch xung quanh: connection.EnlistTransaction(Transaction.Current).

Hoặc, TS có thể được tạo từ giao dịch hiện tại, ví dụ: new TransactionScope(transaction), có thể có hoặc không hữu ích ở đây.

Tạo một giao dịch thủ công nếu hoàn toàn tốt đẹp, nhưng TS (sau khi gotchas được tìm ra!) Làm cho việc đối phó với các giao dịch đơn giản hơn và dễ dàng hơn .. ít nhất là trong hầu hết trường hợp :)

Chúc mừng mã hóa!


TS không được sử dụng cho "báo cáo cập nhật".Nó vẫn sẽ [có khả năng] được sử dụng cho context.SaveChanges() vì điều đó sẽ mở ra một kết nối mới sau đó được tự động gia nhập.

Tôi đã cung cấp một số tùy chọn ở trên, mặc dù tôi không chắc về giao dịch "lồng nhau" đơn giản. Việc thấy API (niêm phong?) Được sử dụng trong ngữ cảnh có thể tiết lộ thêm thông tin chi tiết về các giới hạn/hạn chế.

+0

Bạn đã đúng! Khi tôi đặt 'Open' sau TS mà TS đang dẫn đầu. Và tôi nghĩ rằng trong thực tế điều này cũng nên xảy ra, bởi vì sự kết nối được mở ra bên trong khuôn khổ cũ. Nhưng nó vẫn cam kết. Tôi sẽ phải nghiên cứu sâu hơn một chút về những gì đang diễn ra ở đó và xem liệu một trong những đề xuất của bạn có thể khắc phục được điều này không. Cảm ơn, tôi sẽ quay lại đây. –

+0

Điều này đưa tôi đi đúng hướng. Tôi đã phát hiện ra rằng khuôn khổ cũ để các kết nối mở lâu hơn cần thiết. Vì vậy, nó là không thể sử dụng TransactionScope theo cách tôi muốn mà không thay đổi mã cũ - mà chúng tôi đang rất miễn cưỡng để làm. Tôi sợ chúng ta phải làm vậy. –