TransactionScope so với Giao dịch trong LINQ to SQL


76

Sự khác biệt giữa mẫu giao dịch cổ điển trong LINQ to SQL như:

using(var context = Domain.Instance.GetContext())
{
    try
    {
        context.Connection.Open();
        context.Transaction = context.Connection.BeginTransaction();
        /*code*/
        context.Transaction.Commit();
    }
    catch
    {
        context.Transaction.Rollback();
    }         
}

so với đối tượng TransactionScope

using (var context = Domain.Instance.GetContext())
using (var scope = new TransactionScope())
{
    try
    {
        /*code*/
        scope.Complete();
    }
    catch
    {
    }
}

Câu trả lời:


37

Linq2SQL sẽ sử dụng một giao dịch ngầm. Nếu tất cả các cập nhật của bạn được thực hiện trong một lần Gửi, bạn có thể không cần phải tự xử lý giao dịch.

Từ tài liệu (tôi nhấn mạnh):

Khi bạn gọi SubmitChanges, LINQ to SQL sẽ kiểm tra xem lệnh gọi có nằm trong phạm vi của một Giao dịch hay không hoặc nếu thuộc tính Giao dịch (IDbTransaction) được đặt thành một giao dịch cục bộ do người dùng bắt đầu. Nếu không tìm thấy giao dịch nào, LINQ to SQL sẽ bắt đầu một giao dịch cục bộ (IDbTransaction) và sử dụng nó để thực hiện các lệnh SQL đã tạo. Khi tất cả các lệnh SQL đã được hoàn thành thành công, LINQ to SQL cam kết giao dịch cục bộ và trả về.


10
Nếu bạn cần gửi thứ gì đó có thuộc tính chu kỳ (phổ biến), bạn gặp lỗi trong LINQ to SQL yêu cầu bạn xóa một phần của mỗi tham chiếu 2 chiều, gửi, sửa chữa tham chiếu 2 chiều và gửi lại. Bạn cần phải kết hợp tất cả những điều này trong giao dịch của riêng mình để làm như vậy. Đó là một nhu cầu phổ biến, vì vậy "Đừng lo lắng về nó" không phải là câu trả lời tốt nhất.
Chris Moschini,

76

Cần lưu ý rằng khi sử dụng TransactionScope, không cần try/catchcấu trúc mà bạn có. Bạn chỉ cần gọi Completeđến phạm vi để thực hiện giao dịch khi phạm vi được thoát.

Điều đó đang được nói, TransactionScopethường là một lựa chọn tốt hơn vì nó cho phép bạn lồng các cuộc gọi đến các phương thức khác có thể yêu cầu giao dịch mà bạn không cần phải chuyển trạng thái giao dịch xung quanh.

Khi gọi BeginTransactiontrên DbConnectionđối tượng, bạn phải vượt qua mà đối tượng giao dịch xung quanh nếu bạn muốn thực hiện các hoạt động khác trong cùng một giao dịch, nhưng theo một phương pháp khác nhau.

Với TransactionScope, miễn là phạm vi tồn tại, nó sẽ xử lý mọi thứ đăng ký với hiện tại Transactiontrên luồng, làm cho mã của bạn sạch hơn và dễ bảo trì hơn.

Trên hết, bạn có thêm lợi ích là có thể sử dụng các tài nguyên khác có thể tham gia vào các giao dịch, không chỉ là kết nối với cơ sở dữ liệu.

Cần lưu ý rằng trong các tình huống mà bạn cần khai thác tối đa các kết nối và hoạt động cơ sở dữ liệu của mình, bạn có thể không muốn sử dụng TransactionScope; thậm chí đối với một cơ sở dữ liệu duy nhất, bạn có thể sử dụng Điều phối viên giao dịch phân tán và giao dịch được chuyển thành giao dịch phân tán (ngay cả đối với một kết nối cơ sở dữ liệu duy nhất).

Trong những trường hợp này, trong khi chỉnh sửa thiết kế của mình, bạn có thể muốn xem xét chuyển một giao dịch cụ thể về kết nối.

Hoặc , nếu bạn biết mình sẽ sử dụng nhất quán một tài nguyên (và trên cùng một chuỗi), bạn có thể muốn tạo một lớp tham chiếu đếm kết nối / giao dịch của bạn.

Bạn sẽ tạo một lớp đang xây dựng, tạo tài nguyên của bạn / tăng số lượng. Nó cũng sẽ triển khai IDisposable(trong đó bạn sẽ giảm / phát hành / cam kết / hủy bỏ khi số lượng bằng 0) và lưu trữ số lượng trong một biến đã ThreadStaticAttributeáp dụng cho nó.

Điều này cho phép bạn tách việc quản lý giao dịch khỏi mã logic và vẫn giữ một tài nguyên đơn lẻ khá hiệu quả (thay vì chuyển sang giao dịch phân tán).


Nếu tôi sử dụng một kết nối duy nhất với giao dịch thì nó không giống nhau sao? Tôi có nghĩa là bạn tránh giao dịch phân phối ..
GorillaApe

@Parhs Phụ thuộc vào việc bạn có các tài nguyên giao dịch khác được sử dụng trong giao dịch với một kết nối cơ sở dữ liệu duy nhất hay không.
casperOne

nhà cung cấp của tôi không cho phép các giao dịch lồng nhau (cơ sở dữ liệu), vì vậy vẫn có sự cố?
GorillaApe

2
@Parhs Đó không phải là về nhà cung cấp cơ sở dữ liệu, nhưng bạn có thể có hệ thống tệp giao dịch, dịch vụ web giao dịch, v.v. Nếu những thứ đó được bao gồm trong một giao dịch với một kết nối cơ sở dữ liệu duy nhất, thì DTC sẽ được thực hiện.
casperOne

21

Một khác biệt lớn (bài học rút ra từ cách khó) - TransactionScope sử dụng MS DTC để quản lý giao dịch.

Nếu ứng dụng của bạn chỉ phải quản lý giao dịch cơ sở dữ liệu và không có dịch vụ hoặc cuộc gọi từ xa nào tham gia, bạn có thể bỏ qua các vấn đề tiềm ẩn liên quan đến MS DTC bằng cách sử dụng giao dịch gốc với cơ sở dữ liệu (DbTransactions).


Tôi cũng chỉ học được điều này một cách khó khăn! Nhưng vui mừng khi đã giải quyết được một cơn ác mộng với MSDTC
DevDave

Mayank (hoặc bất kỳ ai khác). Tôi gặp phải vấn đề khác với Giao dịch và Kiểm tra Đơn vị, bạn có thể giúp tôi với stackoverflow.com/questions/9636533/… này không?
DevDave

6
Điều này không đúng mọi lúc. TransactionScopesẽ chuyển từ giao dịch nhân lên đến giao dịch DTC tùy theo nhu cầu. Tuy nhiên, tất cả điều này đều được bạn giấu kín. Điểm quan trọng là nó không phải lúc nào cũng làm điều này, nhưng khi cần thiết .
casperOne

Không nếu bạn sử dụng cùng một văn bản dữ liệu.
Dasith Wijes 17/02/16

7

TransactionScope cung cấp quản lý thống nhất cho tất cả các trình quản lý tài nguyên (máy chủ SQL, thư mục hoạt động, hệ thống tệp,…). Hơn nữa, người ta có thể viết trình quản lý tài nguyên của riêng mình: mã phát hiện phạm vi giao dịch, tham gia và hoạt động chính xác như máy chủ SQL: cam kết hoặc hoàn nguyên các thay đổi giống như những người tham gia giao dịch khác. Tôi tin rằng TransactionScope là chủ đạo và đã quên các giao dịch gốc MS SQL cho đến khi không thành công trong bẫy lớn: Windows Server 2008 WEB Edition đi kèm với Dịch vụ Điều phối viên Giao dịch Phân tán bị hạn chế và phạm vi Giao dịch chỉ hoạt động trên một máy tính. Ứng dụng ASP.NET của bạn sẽ không thành công trên hệ thống này nếu máy chủ IIS và SQL được cài đặt trên các máy tính khác nhau. Hãy lưu ý rằng hầu hết các nhà cung cấp miền công cộng cung cấp phiên bản WEB của Windows Server và máy chủ SQL nằm trên các máy chủ riêng biệt. Điều này có nghĩa là bạn phải làm việc với các giao dịch gốc bằng cách sử dụng quản lý giao dịch rõ ràng…


4

Tôi tin rằng chúng về cơ bản giống nhau là lớp TransactionScope sẽ giao tiếp với kết nối cơ bản ADO.NET để tạo và cam kết hoặc khôi phục giao dịch. Đó là lớp TransactionScope vừa được tạo để làm việc với ADO.NET bền bỉ hơn.

Chỉnh sửa: Làm rõ tuyên bố của tôi liên quan đến việc bổ sung casperOne, đó là TransactionScope sẽ tạo ra giao dịch và kết nối sau đó sẽ thấy giao dịch được tạo bởi TransactionScope và sử dụng nó vì nó có sẵn cho nó.


@Christ Marisic: Đó là cách khác. Kết nối tìm kiếm sự hiện diện của một Giao dịch cho luồng hiện tại, luồng này sẽ được tạo bởi TransactionScope. Nếu có, thì nó sẽ tranh thủ với Giao dịch. Sau đó, điều phối viên sẽ yêu cầu kết nối cam kết hoặc khôi phục.
casperOne
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.