<目次>
(1) .NETで「SystemInvalidOperationException」例外(ZombieCheck、Rollback)の調査記録
(1-1) エラーメッセージ
(1-2) 原因・対処(例)
(1-3) 再現テスト
(1) .NETで「SystemInvalidOperationException」例外(ZombieCheck、Rollback)の調査記録
.NETでDB操作をした際に「SystemInvalidOperationException」が発生した際の調査備忘メモです。
(1-1) エラーメッセージ
(エラーメッセージ)
System.InvalidOperationException: This SqlTransaction has completed; it is no longer usable. at System.Data.SqlClient.SqlTransaction.ZombieCheck() at System.Data.SqlClient.SqlTransaction.Rollback()
(1-2) 原因・対処(例)
あくまで一例ですが、Rollback()やCommit()の処理で発生していました。何かしらの原因で接続がclose()されてしまった場合に、そのクローズされた接続を使ってRollback()やCommit()を実行しようとするとエラーになっているようです。
(1-3) 再現テスト
こちらのサイトを参考に再現を行ったのが以下プログラムですが、ポイントとなる点は次の通りです。
con.Close()
cmd.Connection = con; cmd.ExecuteNonQuery();
※ExecuteNonQueryはデータの返却がないINSERTやUPDATEの実行に使用します。
catch (InvalidOperationException iex)
trn.Rollback();
(Exception再現プログラム)
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SQLExceptionTest
{
class Program
{
static void Main(string[] args)
{
string dataSource, initCatalog, userId, passWord, connectionString;
dataSource = "[ホスト名]";
initCatalog = "[データベース名]";
userId = "[ユーザID]";
passWord = "[パスワード]";
connectionString = @"Data Source=" + dataSource + ";Initial Catalog=" + initCatalog + ";User ID=" + userId + ";Password=" + passWord;
//SELECT文を作成
string query_i = "INSERT INTO dbo.ACCESS_COUNTER VALUES (6,'GOLD',10);";
SqlConnection con = new SqlConnection(connectionString);
SqlTransaction trn;
//接続を確立
con.Open();
trn = con.BeginTransaction();
try
{
//接続を敢えてクローズ
con.Close();
SqlCommand cmd = new SqlCommand(query_i);
cmd.Connection = con;
cmd.ExecuteNonQuery();
}catch (InvalidOperationException iex)
{
Console.WriteLine("# InvalidOperationException #");
Console.WriteLine(iex.Message);
//# ↓ここでクローズされた接続(con)を使ってRollbackしようとしたためエラーになっている
trn.Rollback();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
(図121)
