2015-08-13 18 views
12

Tôi hiện đang cố gắng sử dụng phạm vi giao dịch lồng nhau để truy cập DB dựa vào Cơ sở dữ liệu SQL Azure.Cách sử dụng lồng ghép giao dịch lồng nhau đối với cơ sở dữ liệu SQL Azure

Tôi đang sử dụng đoạn mã sau (Net 4.5.1, mã của tôi là async tất cả các con đường xuống, nó ASP.Net MVC với EF6.1):

public async Task Test() 
{ 
    // In my actual code, the DbContext is injected within the constructor 
    // of my ASP.Net MVC Controller (thanks to IoC and dependency injection) 
    // The same DbContext instance is used for the whole HttpRequest 
    var context = new TestContext(); 

    using (var t1 = StartTransactionForAsync()) 
    { 
     using (var t2 = StartTransactionForAsync()) 
     { 
      context.Users.Add(new User { Name = Guid.NewGuid().ToString() }); 
      await context.SaveChangesAsync(); 

      t2.Complete(); 
     } 
     ... // Some more code here 
     t1.Complete(); 
    } 
} 

private static TransactionScope StartTransactionForAsync() 
{ 
    return new TransactionScope(
     TransactionScopeOption.Required, 
     new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }, 
     TransactionScopeAsyncFlowOption.Enabled); 
} 

Mọi thứ đều tốt, ngoại trừ đôi khi các TransactionScope đang leo thang để MSDTC đó là (rõ ràng) không được hỗ trợ bởi cơ sở dữ liệu SQL Azure. Vì vậy, đôi khi tôi nhận được lỗi sau:

Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool.

tôi có thể thêm Enlist=False đến chuỗi kết nối của tôi, nhưng nó sẽ phá vỡ các mã trên, như giao dịch nội vẫn sẽ chèn vào cơ sở dữ liệu ngay cả khi ngoài TransactionScope được xử lý mà không cần Complete .

Tôi đang nhắm mục tiêu một Cơ sở dữ liệu đơn, sử dụng một đơn Entity Framework bối cảnh cho tôi toàn bộ HttpRequest, luôn với cùng chuỗi kết nối.

Vì vậy, câu hỏi của tôi là: giao dịch

  • được lồng nhau được hỗ trợ bởi cơ sở dữ liệu SQL Azure ở tất cả?
  • tại sao mã trên đôi khi leo thang lên MSDTC?

Các official documentation nói:

Microsoft Azure SQL Database does not support distributed transactions, which are transactions that affect several resources. For more information, see Distributed Transactions (ADO.NET).

Starting with the version 2.0, application transactions may be automatically promoted to distributed transactions. This applies to applications that use the System.Data.SqlClient class to perform database operations in the context of a System.Transactions transaction.

Transaction promotion occurs when you open multiple connections to different servers or databases within a TransactionScope, or when you enlist multiple connections in a System.Transactions object by using the EnlistTransaction method. Transaction promotion also occurs when you open multiple concurrent connections to the same server and database either within the same TransactionScope or by using the EnlistTransaction method.

Starting with the version 3.5, the transaction will not be promoted if the connection strings for the concurrent connections are exactly the same. For more information about transactions and avoiding transaction promotion, see System.Transactions Integration with SQL Server (ADO.NET).

mà không trả lời bất cứ câu hỏi của tôi.

+0

TransactionScope được phát minh cho giao dịch * ngầm/tự động * (tận dụng dịch vụ MSDTC), không dành cho giao dịch * lồng nhau *. Có vẻ như bạn đang bối rối những thuật ngữ đó.Chuyển đến DTC có thể xảy ra bởi vì bạn có một số công cụ async (có nghĩa là các luồng khác nhau, có thể có nghĩa là các kết nối khác nhau). Tôi hầu như không thấy lý do tại sao bạn muốn đặt công cụ async trong loại (máy chủ?) Mã - vượt ra ngoài thời trang hiện tại xung quanh "async" :-). Thêm thông tin về leo thang tại đây: http://stackoverflow.com/questions/1690892/transactionscope-automatically-escalating-to-msdtc-on-some-machines –

+0

@SimonMourier Tôi không chắc tôi hiểu câu đầu tiên của bạn; 'TransactionScope' chắc chắn hỗ trợ các giao dịch lồng nhau (xem ví dụ http://stackoverflow.com/a/2742025/870604). Rollbacking phạm vi gốc nên rollback toàn bộ hoạt động. Đối với các công cụ async, tôi đang sử dụng nó vì lý do khả năng mở rộng/hiệu suất. Điều đó nói rằng, nó không thay đổi thực tế là ngay cả khi hai hoạt động được thực thi trên hai luồng khác nhau, chúng vẫn sử dụng cùng một kết nối DB (một cá thể DbContext duy nhất được sử dụng). – ken2k

+0

Tôi chưa bao giờ nói TS không hỗ trợ các giao dịch lồng nhau. Tôi nói rằng bạn đang bối rối cả hai khái niệm. Giao dịch lồng nhau tồn tại lâu trước khi DTC tồn tại. Bạn có thể thực hiện giao dịch lồng nhau w/o TS, nhưng bạn đang nói về * phạm vi lồng nhau *. Async sẽ không mang lại bất kỳ lợi ích khả năng mở rộng nào ở đây, nếu đằng sau hiện trường, bạn đang sắp xếp trên một kết nối duy nhất (thực tế có thể tệ hơn), mà tôi vẫn còn nghi ngờ. IMHO bạn nên hiển thị một mã repro đầy đủ để tránh đoán hoang dã. –

Trả lời

2

Hãy thử này thêm vào chuỗi kết nối của bạn, nó bật Multiple Active Result Sets. Điều này nghĩa vụ phải dừng vấn đề MSDTC; mặc dù tôi không chắc chắn về điều này.

MultipleActiveResultSets=True; 

Về thông tin thêm, nested transaction is not really nested transaction.

+0

Tôi đã tin rằng MARS đã được kích hoạt, nhưng sau khi kiểm tra lại chuỗi kết nối của tôi, nó thực sự là không. Trừ khi cho Azure DB nó hoạt động theo mặc định, điều này thực sự có thể là vấn đề của tôi – ken2k

+0

Tôi đang hết thời gian (trước khi kết thúc tiền thưởng) để kiểm tra đầy đủ nếu điều này khắc phục vấn đề của tôi, nhưng điều này thực sự là một vấn đề với chuỗi kết nối của tôi (Tôi đã chắc chắn MARS đã được kích hoạt, nhưng nó thực sự là không). Việc sửa chữa có vẻ đầy hứa hẹn, vì vậy tôi sẽ cho bạn tiền thưởng + tiền thưởng, nhưng tôi sẽ chấp nhận câu trả lời sau sau khi tôi có thể kiểm tra mọi thứ đúng cách. Cảm ơn! – ken2k

0

MSDN: Khuyến mại giao dịch cho DTC có thể xảy ra khi kết nối bị đóng và mở lại trong một giao dịch. Vì khung Entity mở và tự động đóng kết nối, bạn nên cân nhắc việc mở và đóng kết nối theo cách thủ công để tránh quảng bá giao dịch.

Để Tránh kịch bản này: How to Manually Open the Connection from the Object Context

0

Cơ sở dữ liệu SQL Azure bây giờ hỗ trợ xúc tiến của một giao dịch với một giao dịch phân phối từ TransactionScope. Điều đó bây giờ làm cho nó có thể sử dụng TransactionScope nơi nó trước đây không thể vì MSDTC không được hỗ trợ. Kết quả là, bạn không nhất thiết cần phải kiểm soát kết nối mở và đóng như được đề xuất trong câu trả lời trước đó. Xem: https://azure.microsoft.com/en-us/documentation/articles/sql-database-elastic-transactions-overview/.

Cũng lưu ý rằng Azure DB hiện vẫn không hỗ trợ hoàn toàn nhiều Bộ kết quả hoạt động.

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