.NETで複数のSqlConnectionsに単一のSqlTransactionを使用する方法は?
-
03-07-2019 - |
質問
- SQL Server 2000を使用しています。 MultipleActiveResultsをサポートしていません。
- 複数の挿入を行う必要があり、挿入ごとに1つの接続で行われます。
- すべての挿入前にトランザクションを開始し、すべての挿入後に終了したい。
- どうすればいいですか
解決
1つの接続と複数のコマンド(実際にはループで再作成された1つのコマンド)を使用しない理由は何ですか? たぶん、このソリューションはあなたのために働くでしょう:
public static void CommandExecNonQuery(SqlCommand cmd,
string query, SqlParameter[] prms)
{
cmd.CommandText = query;
cmd.Parameters.AddRange(prms);
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
static void Main(string[] args)
{
string insertQuery =
@"INSERT TESTTABLE (COLUMN1, COLUMN2) " +
"VALUES(@ParamCol1, @ParamCol2)";
using (SqlConnection connection =
new SqlConnection(connectionString))
{
using (SqlCommand command =
connection.CreateCommand())
{
SqlTransaction transaction = null;
try
{
// BeginTransaction() Requires Open Connection
connection.Open();
transaction = connection.BeginTransaction();
// Assign Transaction to Command
command.Transaction = transaction;
for (int i = 0; i < 100; i++)
CommandExecNonQuery(command, insertQuery,
new SqlParameter[] {
new SqlParameter("@ParamCol1", i),
new SqlParameter("@ParamCol2", i.ToString()) });
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
finally
{
connection.Close();
}
}
}
}
こちらもご覧ください
SQL Serverトランザクション-ADO.NET 2.0-コミットとロールバック-使用ステートメント-IDisposable
他のヒント
.NET 2.0を使用しているかどうかは指定しませんでしたが、その仮定をします。 C#3.0のサンプルコードは次のとおりです。
using (var tx = new TransactionScope()) {
// Execute multiple DB statements inside here
ts.Complete();
}
DBステートメントのいずれかが失敗した場合、ts.completeに到達することはなく、usingステートメントの最後にトランザクションが自動的にロールバックされます。ただし、このアプローチの1つの注意点は、複数の接続を使用するとDTCを利用することになり、パフォーマンスが低下することです。
SqlTransactionをTransactionScopeに変更するように編集
単一のSQL接続を強制してDTCの使用を回避する例:
using (var tx = new TransactionScope())
using (var db = new SqlConnection(connString)) {
// Command 1
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
// Command 2
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
// Command 3
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
tx.Complete();
}
トランザクションは接続で作成され、作成された接続を超えるスコープはないため、要求したことを実行できません。リファクタリングして、同時ではなく接続で順次挿入を実行したり、ロールバックを実現するための別のメカニズムを実装したりすることができます(例:挿入されたキーのテーブル。プロセス)
トランザクションが複数の接続にまたがることはないと思います。
別々の接続で複数の挿入を行う理由は何ですか?通常は単一の接続でそれらが欲しいと思うでしょう。
所属していません StackOverflow