2010-03-23 34 views
12

Tôi có một thường trình sử dụng vòng lặp đệ quy để chèn các mục vào cơ sở dữ liệu SQL Server 2005 Cuộc gọi đầu tiên khởi tạo vòng lặp được bao bọc trong một giao dịch bằng TransactionScope. Khi tôi lần đầu tiên gọi ProcessItem, dữ liệu myItem được chèn vào cơ sở dữ liệu như mong đợi. Tuy nhiên khi ProcessItem được gọi từ ProcessItemLinks hoặc ProcessItemComments, tôi nhận được lỗi sau.Tại sao thao tác TransactionScope không hợp lệ?

“Các hoạt động không hợp lệ cho tình trạng giao dịch”

Tôi đang chạy này trong debug với VS 2008 trên Windows 7 và có các MSDTC chạy để cho phép các giao dịch phân tán. Mã bên dưới không phải là mã sản xuất của tôi nhưng được đặt chính xác như nhau. AddItemToDatabase là một phương thức trên một lớp mà tôi không thể sửa đổi và sử dụng một ExecuteNonQuery chuẩn() để tạo ra một kết nối sau đó đóng và hủy bỏ khi đã hoàn tất.

Tôi đã xem các bài đăng khác trên đây và Internet và vẫn không thể giải quyết vấn đề này. Bất kì sự trợ giúp nào đều được đánh giá cao.

using (TransactionScope processItem = new TransactionScope()) 
{ 
    foreach (Item myItem in itemsList) 
    { 
     ProcessItem(myItem); 
    } 
    processItem.Complete(); 
}  
private void ProcessItem(Item myItem) 
{ 
    AddItemToDatabase(myItem); 
    ProcessItemLinks(myItem); 
    ProcessItemComments(myItem); 
}  
private void ProcessItemLinks(Item myItem) 
{ 
    foreach (Item link in myItem.Links) 
    { 
     ProcessItem(link); 
    } 
} 
private void ProcessItemComments(Item myItem) 
{ 
    foreach (Item comment in myItem.Comments) 
    { 
     ProcessItem(comment); 
    } 
} 

Đây là phần trên cùng của dấu vết ngăn xếp. Rất tiếc, tôi không thể hiển thị việc xây dựng đến thời điểm này như thông tin nhạy cảm của công ty mà tôi không thể tiết lộ.

at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction) 
    at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification) 
    at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx) 
    at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx) 
    at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction) 
    at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction) 
    at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) 
    at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) 
    at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) 
    at System.Data.SqlClient.SqlConnection.Open() 
+0

Bạn có thể đăng stack trace của ngoại lệ? –

+0

Tôi đã thêm nhiều dấu vết như được cho phép. Hy vọng nó là đủ! – Cragly

+0

Bạn có thể đăng toàn bộ ngoại lệ không? Đăng đầu ra của ex.ToString(), sau đó làm lại mọi thứ nhạy cảm. Tôi tự hỏi nếu có một InnerException hoặc hai. –

Trả lời

23

giao dịch phân tán làm tóc của tôi đi màu xám sớm :)

Usual Suspects

  1. Firewall chặn MSDTC
  2. Giao dịch của bạn là thời điểm ra đối với một số lý do (thử tăng thời gian chờ)
  3. Bạn có một phạm vi giao dịch khác ở đâu đó trên đầu mã đang gây rối với giao dịch hiện tại

thử nghiệm liệu MSDTC đang làm việc tốt bằng các công cụ như dtcping

Ngoài ra kiểm tra bằng cách chèn một số nhỏ các nguyên tố ban đầu. Mã của bạn dường như nằm trong một vòng lặp đệ quy có thể xử lý một lượng lớn dữ liệu. Có thể bạn đang chạy đến nhiều truy vấn và giao dịch hết thời gian.

Đôi khi System.Transactions.Transaction.Current có một số manh mối về những gì đã xảy ra. Thêm đồng hồ với biến toàn cục này

+0

Vâng tóc của tôi đã bắt đầu rơi ra! Sẽ cung cấp thông tin cập nhật về cách tôi tiếp tục với các đề xuất ở trên. – Cragly

+2

+1 cho "làm tóc của tôi chuyển sang màu xám" .. đó là một câu chuyện có thật –

+1

Hết thời gian chờ tôi một vài lần. Thật dễ dàng để quên đi giao dịch phân tán, đặc biệt là khi gỡ lỗi. Nó đáng chú ý là mặc định chỉ là 1 phút. Bạn có thể tăng nó (ví dụ như 10mins) bằng cách thêm nó vào app.config của bạn - '', hoặc truyền vào như một tham số tới 'TransactionScope()' – Rhumborl

0

Thời gian chờ tối đa mặc định là 10 phút. Bạn có thể ghi đè này nằm ở cùng Machine.config tuy nhiên:

<configuration> 
    <system.transactions> 
     <machineSettings maxTimeout="00:00:30" /> 
    </system.transactions> 
</configuration> 

Hoặc bạn có thể sử dụng phản ánh để ghi đè lên nó trong mã:

private static void OverrideTransactionScopeMaximumTimeout(TimeSpan timeOut) 
    { 

     // 1. create a object of the type specified by the fully qualified name 

     Type oSystemType = typeof(global::System.Transactions.TransactionManager); 

     System.Reflection.FieldInfo oCachedMaxTimeout = oSystemType.GetField("_cachedMaxTimeout", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); 

     System.Reflection.FieldInfo oMaximumTimeout = oSystemType.GetField("_maximumTimeout", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); 

     oCachedMaxTimeout.SetValue(null, true); 

     oMaximumTimeout.SetValue(null, timeOut); 

     // For testing to confirm value was changed 

     // MessageBox.Show(string.Format(&quot;DEBUG SUCCESS!! &nbsp;Maximum Timeout for transactions is &#39;{0}&#39;&quot;, TransactionManager.MaximumTimeout.ToString())); 

    } 

Thông tin thêm: https://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/

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