2010-03-23 8 views
12

재귀 루프를 사용하여 SQL Server 2005 데이터베이스에 항목을 삽입하는 루틴이 있습니다. 루프를 시작하는 첫 번째 호출은 TransactionScope를 사용하여 트랜잭션 내에 포함됩니다. 처음 ProcessItem을 호출하면 myItem 데이터가 예상대로 데이터베이스에 삽입됩니다. 그러나 ProcessItemLinks 또는 ProcessItemComments에서 호출 될 때 다음 오류가 발생합니다.왜 TransactionScope 작업이 유효하지 않습니까?

나는 윈도우 7에 VS 2008 디버깅이를 실행하고 "작업은 트랜잭션의 상태에 대해 유효하지 않습니다"와 MSDTC는 분산 트랜잭션을 사용하는 실행했다. 아래 코드는 제 제작 코드가 아니지만 정확히 동일하게 설정되어 있습니다. AddItemToDatabase는 수정할 수없는 클래스의 메서드이며 표준 ExecuteNonQuery()를 사용하여 연결을 만든 다음 완료되면 처리하고 닫습니다.

다른 게시글을 인터넷에서 보았지만 여전히이 문제를 해결할 수 없습니다. 어떤 도움이라도 대단히 감사 할 것입니다.

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); 
    } 
} 

여기는 스택 추적의 상단 부분입니다. 불행하게도이 시점까지 내가 공개 할 수없는 회사의 민감한 정보로 보여줄 수는 없습니다.

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

당신이 스택 추적을 게시 할 수 예외? –

+0

허용되는만큼 추적을 추가했습니다. 희망은 충분하다! – Cragly

+0

전체 예외를 게시 할 수 있습니까? ex.ToString()의 출력을 게시 한 다음 중요한 내용을 수정하십시오. InnerException 또는 2가 있는지 궁금하네요. –

답변

23

분산 트랜잭션이 내 머리를

  1. 방화벽은 MSDTC를 차단 : 회색 조기에 갈

    평소 용의자했다

  2. 귀하의 트랜잭션 (제한 시간을 늘려보십시오) 어떤 이유로 시간이 초과되어
  3. 다른 트랜잭션 범위가 현재 트랜잭션의 코드 상단에 있습니다.
  4. MSDTC 잘 작동 처음에는 적은 소자 수를 삽입하여도

    시험 DTCPing에서 같은 도구를 사용하는지 여부

시험. 코드가 많은 양의 데이터를 처리 할 수있는 재귀 루프에있는 것 같습니다. 어쩌면 많은 쿼리를 실행하고 트랜잭션이 시간 초과 될 수 있습니다.

Sometime System.Transactions.Transaction.Current에는 일어난 일에 대한 단서가 있습니다. 이 전역 변수에 대한 감시 장치 추가

+0

그래, 내 머리가 빠지기 시작했다! 위의 제안을 어떻게 받아 들일지에 대한 업데이트를 제공 할 것입니다. – Cragly

+2

+1은 "내 머리가 회색으로 바뀌 었습니다".. 실화입니다 –

+1

시간 초과로 두 번 걸렸습니다. 특히 디버깅 할 때 분산 트랜잭션을 쉽게 잊을 수 있습니다. 기본값은 1 분입니다. 이 값을 app.config -''에 추가하거나 매개 변수로 전달하여 (예 : 10 분으로) 늘릴 수 있습니다 'TransactionScope()'에 – Rhumborl

0

기본 최대 시간 초과는 10 분입니다. 당신이 그러나이 Machine.config에 재정의 할 수

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

또는 당신은 코드에서 재정의 반사를 사용할 수 있습니다

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())); 

    } 

상세 정보 : https://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/

관련 문제