2014-04-04 2 views
0

을 잠글, 그것은 테이블에 공유 잠금을 생성합니다. 나중에 커밋을하더라도. 어떻게 방지합니까? (또는 내가 뭘 잘못하고 있니?)삽입 기록의 원인은

DbCommand command = new SACommand(); 
    command.CommandTimeout = this.Timeout; 
    bool mustCloseConnection = false; 
    PrepareCommand(command, connection, null, commandType, commandText, commandParameters, ref mustCloseConnection); 
    int num2 = command.ExecuteNonQuery(); 
    command.Parameters.Clear(); 
    if (mustCloseConnection) 
    { 
     connection.Close(); 
    } 


    private void PrepareCommand(IDbCommand command, IDbConnection connection, IDbTransaction transaction, CommandType commandType, string commandText, IDataParameter[] commandParameters, ref bool mustCloseConnection) 
    { 
     if (command == null) 
     { 
      throw new ArgumentNullException("command"); 
     } 
     if ((commandText == null) || (commandText.Length == 0)) 
     { 
      throw new ArgumentNullException("commandText"); 
     } 
     if (connection.State != ConnectionState.Open) 
     { 
      connection.Open(); 
      mustCloseConnection = true; 
     } 
     else 
     { 
      mustCloseConnection = false; 
     } 
     command.Connection = connection; 
     command.CommandText = commandText; 
     command.CommandTimeout = this.Timeout; 
     if (transaction != null) 
     { 
      if (transaction.Connection == null) 
      { 
       throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction"); 
      } 
      command.Transaction = transaction; 
     } 
     command.CommandType = commandType; 
     if (commandParameters != null) 
     { 
      AttachParameters(command, commandParameters); 
     } 
    } 
+1

우리는 PrepareCommand'는 –

+0

추가 준비하는 일'볼 필요를 명령은 SQL Server 버전의 코드에서 직접 해제되었습니다. –

답변

1

좋아, 일부 문서를 확인할 수 있습니다 http://infocenter.sybase.com/help/topic/com.sybase.help.sqlanywhere.12.0.1/pdf/dbprogramming12.pdf

Cursor behavior when opening cursors 
You can configure the following aspects of cursor behavior when you open the cursor: 
● Isolation level You can explicitly set the isolation level of operations on a cursor to be different 
from the current isolation level of the transaction. To do this, set the isolation_level option. 
● Holding By default, cursors in embedded SQL close at the end of a transaction. Opening a cursor 
WITH HOLD allows you to keep it open until the end of a connection, or until you explicitly close it. 
ADO.NET, ODBC, JDBC, and Open Client leave cursors open at the end of transactions by default 

어쩌면 좀 더 신선한 문서가 있습니다,하지만 난 것은 아무것도가 변경되었습니다하지 않습니다. . 난 당신이 HOLD 커서를이 거의 확실 그렇게 후에도이 열려 COMMIT.

사실은 이미 .. 당신이 연결을 종료해야하는 이유를 설명하지 않고, 난이 도움이되기를 바랍니다

...

1

연결 및 명령 개체는 폐기해야합니다. 폐기에 전화하거나이 같은 using 문에 포장 : 내 명령 개체를 배치하지 않았기 때문에 나는 MSSQL과 같은 오류를 했어

using (IDBConnection con = new DbConnection()) 
{ 
    using (IDBCommand com = new DbCommand()) 
    { 
    // do your sql stuff here 
    } 
    con.Close(); 
} 

(단지 예를 들어 입력 코드).

SQL Anywhere® Server - Programming > Using SQL in Applications > Controlling transactions in applications > Cursors and transactions 
In general, a cursor closes when a COMMIT is performed. There are two exceptions to this behavior: 

The close_on_endtrans database option is set to Off. 

**A cursor is opened WITH HOLD**, which is the default with Open Client and JDBC. 

If either of these two cases is true, the cursor remains open on a COMMIT. 

그리고 그 하나 :

1

을 그 대답을 당신은 모든 연결, 명령, 거래는 100 % 확신하는 경우 등이 정상적으로 다음 당신은 당신의 거래를 인스턴스화하는 방법을 확인 할 수 있습니다, 배치 얻고있다.

하여 TransactionScope의 기본 생성자

잘못 마이크로 소프트에 의해 설계되었습니다 조만간이 (비슷한 문제가 다른 트랜잭션 클래스에 적용 할 수있는) 잠금이 발생합니다. 기본 생성자는 잠금을 유발하는 "Serializable isolation level"을 사용합니다.

문제가 더 심각합니다. SQL 작업이 실패하고 롤백을 수행하는 경우 더 나은 격리 수준 (예 : ReadCommitted)으로 TransactionScope를 인스턴스화하면 내부적으로 격리 수준이 다시 " 같은 트랜잭션 인스턴스를 사용하여 다른 명령을 잠금하는 경향이있을 것이다 "직렬화.

이것은 Microsoft에 버그로보고되었으며 MS는 단순히 "일반적으로 버그입니다. 시스템에 영향을 줄 수 있기 때문에 해결할 수 없으며 왜 TransactionScope 인스턴스를 기본 생성자를 사용하여? "절대로 그렇게해서는 안됩니다.

TransactionScope 클래스를 사용하는 유일한 안전한 방법은 항상 잠금을 발생시키지 않는 원하는 격리 수준을 사용하여 항상 인스턴스화하는 것입니다 (일반적인 시나리오는 ReadCommitted를 사용하지만 다른 것들도 사용할 수 있습니다) . 여기 http://blogs.msdn.com/b/dbrowne/archive/2010/06/03/using-new-transactionscope-considered-harmful.aspx?Redirected=true에서 제안 된

당신은 정적 빌더를 사용할 수 있습니다 :

public class TransactionUtils { 
    public static TransactionScope CreateTransactionScope() 
    { 
    var transactionOptions = new TransactionOptions(); 
    transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted; 
    transactionOptions.Timeout = TransactionManager.MaximumTimeout; 
    return new TransactionScope(TransactionScopeOption.Required, transactionOptions); 
    } 
} 

또는 사용자 정의 래퍼 클래스 사용 :

namespace System.Transactions { 
    /************************************************************************************************************** 
    * IMPORTANT: This class must ALWAYS be used instead of the regular "TransactionScope" class. This class 
    * enforces having transactions that read "only committed" data. 
    * 
    * This is because the implementation of TransactionScope is faulty (wrong design) and it gives issues because 
    * it changes the connections available at the the connection pool. To read more, check this link: 
    * http://blogs.msdn.com/b/dbrowne/archive/2010/05/21/using-new-transactionscope-considered-harmful.aspx 
    * 
    * The namespace was set to "System.Transactions" in order to provide ease of use when updating legacy code 
    * that was using the old class 
    **************************************************************************************************************/ 
    public class SafeTransactionScope : IDisposable { 
     private TransactionScope _transactionScope; 
     private bool _disposed; 

     #region Constructors 
     public SafeTransactionScope() 
      : this(TransactionManager.MaximumTimeout) { 
     } 

     public SafeTransactionScope(TimeSpan scopeTimeout) 
      : this(TransactionScopeOption.Required, scopeTimeout) { 
     } 

     public SafeTransactionScope(TransactionScopeOption scopeOption) 
      : this(scopeOption, TransactionManager.MaximumTimeout) { 
     } 

     public SafeTransactionScope(TransactionScopeOption scopeOption, TimeSpan scopeTimeout) { 
      this._disposed = false; 
      this._transactionScope = CreateTransactionScope(scopeOption, scopeTimeout); 
     } 
     #endregion 

     #region Disposing methods 
     public void Dispose() { 
      Dispose(true); 

      // Use SupressFinalize in case a subclass 
      // of this type implements a finalizer. 
      GC.SuppressFinalize(this); 
     } 

     private void Dispose(bool disposing) { 
      if(!this._disposed) { 
       if(disposing) { 
        if(this._transactionScope != null) { 
         this._transactionScope.Dispose(); 
         this._transactionScope = null; 
        } 
       } 

       // Indicate that the instance has been disposed. 
       this._disposed = true; 
      } 
     } 
     #endregion 

     public void Complete() { 
      if(this._disposed) { 
       throw new ObjectDisposedException("SafeTransactionScope"); 
      } 

      if(this._transactionScope == null) { 
       // This should never happen 
       throw new ObjectDisposedException("SafeTransactionScope._transactionScope"); 
      } 

      this._transactionScope.Complete(); 
     } 

     private static TransactionScope CreateTransactionScope(TransactionScopeOption scopeOption, TimeSpan scopeTimeout) { 
      var transactionOptions = new TransactionOptions() { 
       IsolationLevel = IsolationLevel.ReadCommitted, 
       Timeout = scopeTimeout 
      }; 

      return new TransactionScope(scopeOption, transactionOptions); 
     } 
    } 
} 
관련 문제