以下は、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) をいくつか使用します。これをエラーなしで実行するために、これらを複製することを余儀なくされました。それらが変数を共有して、それらを再作成するためにスペースを無駄にする必要がないようにする方法はありますか?