SqlTransaction データベーストランザクション

トランザクション(Transaction):複数のSQL操作をアトミックに実行し、すべて成功すればコミット(Commit)、どこかで失敗すれば全部ロールバック(Rollback)する仕組みで、ACID特性を満たします。
.NET Framework/.NET では SqlTransaction(SQL Server専用)を使って実装します。

処理のポイント:

  1. データベース接続を開く conn.Open()
  2. 接続からトランザクションを開始 conn.BeginTransaction()
  3. トランザクションオブジェクトを SqlCommand.Transaction に紐付け
  4. 複数のSQLを一括実行
  5. 例外なし:tx.Commit();例外発生時:tx.Rollback()

サンプルコード

元のコードにはcatchによるロールバック処理がないため、完全な動作可能版を示します:

public static int ExecuteSqlTran(List<string> SQLStringList)
{
    using (SqlConnection conn = new SqlConnection(connectionString))
    {
        conn.Open();
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = conn;
        SqlTransaction tx = conn.BeginTransaction();
        cmd.Transaction = tx;
        try
        {
            int count = 0;
            for (int n = 0; n < SQLStringList.Count; n++)
            {
                string strsql = SQLStringList[n];
                if (strsql.Trim().Length > 1)
                {
                    cmd.CommandText = strsql;
                    count += cmd.ExecuteNonQuery();
                }
            }
            tx.Commit(); // 全て成功したらコミット
            return count;
        }
        catch (Exception ex)
        {
            tx.Rollback(); // 1つでも失敗したら全てロールバック
            throw ex; // 上位側へ例外を再スローして失敗を通知
        }
    }
}Code language: C# (cs)

このコードはSQL文字列を直接連結しておりSQLインジェクションの危険があります。トランザクションの仕組み理解用として使用し、実際の開発ではパラメータ化クエリを優先してください。

パラメータを使用したトランザクション例

SqlParameterを利用してインジェクションを防ぎつつループでデータを挿入します。重要なポイント:

  1. ループの末尾で sqlCom.Parameters.Clear() を呼び出し、前回のパラメータを削除してエラーを回避する
  2. 同一のSqlCommandインスタンスを再利用し、CommandTextとパラメータだけ更新する
SqlCommand sqlCom = new SqlCommand();
sqlCom.Connection = conn;
SqlTransaction st = conn.BeginTransaction();
sqlCom.Transaction = st;
int res = 0;
try
{
    for (int i = 0; i < 10; i++)
    {
        sqlCom.CommandText = "INSERT INTO [dbo].[Article]([Title])VALUES(@Title)";
        SqlParameter param = new SqlParameter("@Title", SqlDbType.NVarChar, 250);
        param.Value = i + "新しいタイトル" + DateTime.Now;
        sqlCom.Parameters.Add(param);
        res += sqlCom.ExecuteNonQuery();
        sqlCom.Parameters.Clear(); // 次ループのためパラメータをクリア
    }
    st.Commit();
}
catch (Exception)
{
    st.Rollback(); // 例外発生時は全操作を取り消し
}Code language: C# (cs)

1. 必ず守るべきルール

  • BeginTransaction()接続Openの後で実行する
  • SqlCommand には Transaction プロパティを設定しないと例外が発生します
  • Commit() / Rollback() 実行後はトランザクションが終了するため、重複呼び出しはできません

その他

  • .NET Core/.NET 5+ では using により SqlTransaction を自動解放することを推奨
  • 大量データを一括処理する場面では SqlBulkCopy を検討してください。ループでExecuteNonQueryを回すより高速です
  • データベースをまたぐトランザクションにはSqlTransactionは対応していません。分散トランザクションのTransactionScopeを使用します

SqlTransaction データベーストランザクション

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です