1

以下は、SSIS スクリプト タスクで使用しているコードです。同様の顧客を扱うため、両方の挿入をアトミックにしようとしています。

最初の.executeNonQuery()ものは正常に機能し、SQL テーブルをロックします。

2番目.executNonQuery()はエラーをスローします:

ExecuteNonQuery では、コマンドに割り当てられた接続が保留中のローカル トランザクションにある場合、コマンドにトランザクションが必要です。コマンドのトランザクション プロパティが初期化されていません。

コード:

    ConnectionManager cm; 
    SqlTransaction sqlTrans;
    SqlConnection sqlConn;
    SqlCommand sqlComm;                                  
    cm = Dts.Connections["connectionManager"];

    try
    {
         //Set 'global' variables                                        
         SqlParameter agentID = new SqlParameter("@agentID", 1000018); //retrievedMessage.Substring(2, 10));//Primary key
         SqlParameter lastChangeOperator = new SqlParameter("@lastChangeOperator", "LVO");
         SqlParameter lastChangeDate = new SqlParameter("@lastChangeDate", DateTime.Now);
         SqlParameter controlId = new SqlParameter("@controlID", 1); //Hard-coded value for testing - CHANGE LATER

         //Set variables for Agent table
         SqlParameter entityType = new SqlParameter("@entityType", "P");//retrievedMessage.Substring(162, 1));
         SqlParameter fName = new SqlParameter("@fName", "test");//retrievedMessage.Substring(12, 25));
         SqlParameter lName = new SqlParameter("@lName", "test");//retrievedMessage.Substring(37, 35));
         SqlParameter suffix = new SqlParameter("@suffix", "test");//retrievedMessage.Substring(72, 10));
         SqlParameter corporateName = new SqlParameter("@corporateName", "Initech");//retrievedMessage.Substring(82, 80));

         //Insert record into Agent table
         sqlConn = (SqlConnection)cm.AcquireConnection(Dts.Transaction);
         sqlComm = new SqlCommand
         (
           "SET IDENTITY_INSERT Agent ON " +
           "INSERT INTO Agent (UniqueAgentId, EntityType, FirstName, LastName, NameSuffix, CorporateName, LastChangeOperator, LastChangeDate, ControlId) " +
           "VALUES (@agentID, @entityType, @fName, @lName, @suffix, @corporateName, @lastChangeOperator, @lastChangeDate, @controlID)" +
           "SET IDENTITY_INSERT Agent OFF",
            sqlConn//, sqlTrans
         );

         sqlTrans = sqlConn.BeginTransaction("SqlAgentTableUpdates");
         sqlComm.Parameters.Add(agentID);
         sqlComm.Parameters.Add(lastChangeOperator);
         sqlComm.Parameters.Add(lastChangeDate);
         sqlComm.Parameters.Add(controlId);
         sqlComm.Parameters.Add(entityType);
         sqlComm.Parameters.Add(fName);
         sqlComm.Parameters.Add(lName);
         sqlComm.Parameters.Add(suffix);
         sqlComm.Parameters.Add(corporateName);
         sqlComm.Transaction = sqlTrans;
         sqlComm.ExecuteNonQuery();

         //Set variables for AgentIdentification table
         SqlParameter taxIdType = new SqlParameter("taxIdType", "S");//Hard-coded value for testing - CHANGE LATER
         SqlParameter agentTaxId = new SqlParameter("@agentTaxId", "999999999");//Hard-coded value for testing - CHANGE LATER

         //Insert record into AgentIdentification table
         sqlConn = (SqlConnection)cm.AcquireConnection(Dts.Transaction);
         sqlComm = new SqlCommand
         (
           "INSERT INTO AgentIdentification (UniqueAgentId, TaxIdType, AgentTaxId, LastChangeOperator, LastChangeDate, ControlId) " +
           "VALUES (@agentID, @taxIdType, @agentTaxId, @lastChangeOperator, @lastChangeDate, @controlId)",
            sqlConn//, sqlTrans
         );

         sqlComm.Parameters.Add(taxIdType);
         sqlComm.Parameters.Add(agentTaxId);
         sqlComm.Transaction = sqlTrans;
         sqlComm.ExecuteNonQuery();
    }
    catch (Exception)
    {
       sqlTrans.Rollback();
       cm.ReleaseConnection(sqlConn);
    }
    finally
    {
       sqlTrans.Commit();
       cm.ReleaseConnection(sqlConn);
    }

編集

2 番目の接続を削除することで、このトランザクションを機能させることができました。ただし、どちらのクエリも同じ変数 (SqlParameters) をいくつか使用します。これをエラーなしで実行するために、これらを複製することを余儀なくされました。それらが変数を共有して、それらを再作成するためにスペースを無駄にする必要がないようにする方法はありますか?

4

3 に答える 3

0

問題は接続にある可能性があると思います。または、コマンドを 2 番目の挿入用の新しいコマンドに設定すると、同じ接続で 2 つの異なるコマンドを使用するか、CommandText プロパティを変更するだけで 1 つのコマンドを再利用できます。

これが役に立てば幸いです... SqlTransactionの使用

于 2012-08-16T04:49:59.757 に答える
0

トランザクションは複数の接続にまたがることはできません...cm.AcquireConnection毎回新しい接続を返しますか? その場合は、両方のコマンドに同じ接続を使用してみてください。

于 2012-08-16T04:43:46.310 に答える
0

トランザクションスコープを使用する

using(TransactionScope ts = new TransactionScope())
{

        using(SqlConnection conn = new SqlConnection(myconnstring)
        {
            conn.Open();
    //call first executenonquery
    //call second executenonquery
            ts.Complete();
            conn.Close();
        }
}
于 2012-08-16T04:43:53.250 に答える