<目次>
(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)