Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

C#

.NETで「SystemInvalidOperationException」例外(ZombieCheck、Rollback)の調査記録

投稿日:2021年5月29日 更新日:

<目次>

(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) 再現テスト

こちらのサイトを参考に再現を行ったのが以下プログラムですが、ポイントとなる点は次の通りです。

(再現STEP1)接続(con)をOpenした後、tryの一番最初でその接続をClose
con.Close()

 

(再現STEP2)クローズされた接続(con)を使ってSQL(INSERT文)を実行
cmd.Connection = con;
cmd.ExecuteNonQuery();

※ExecuteNonQueryはデータの返却がないINSERTやUPDATEの実行に使用します。

(再現STEP3)InvalidOperationException例外が発生し、それをキャッチ
catch (InvalidOperationException iex)

 

(再現STEP4)catchした中でRollbackするとClose済の接続のため例外が起きる
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)

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-C#

執筆者:


comment

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

関連記事

C#のコンソールアプリで引数を与えて実行する方法

<目次> (1) C#のコンソールアプリで引数を与えて実行する方法  (1-1) 設定箇所  (1-2) サンプルプログラム  (1-3) サンプルプログラムの補足 (1) C#のコンソールアプリで引 …

C#のデリゲートが分からない・・を解決!初心者向けになるべく分かり易く説明してみた

<目次> (1) C#のデリゲートが分からない・・を解決!初心者向けになるべく分かり易く説明してみた  (1-1) デリゲートとは?「関数へのポインタ」だけでは説明しきれない・・  (1-2) デリゲ …

ASP.NETでViewに値を渡す方法

  <目次> (1) ASP.NETでViewに値を渡す方法  (1-1) 方法1:アクションメソッドの引数に追加  (1-2) 方法2:ViewBagを使う方法  (1-3) 方法3:ビュ …

ASP.NET MVCのRouteConfigを追加する方法を2つご紹介

  <目次> (1) ASP.NET MVCのRouteConfigを追加する方法を2つご紹介  (1-1) やりたい事の整理  (1-2) 方法1:通常のルーティング  (1-3) 方法2 …

ASP.NETのbootstrapとは?概要と入手・適用方法のご紹介

  <目次> (1) ASP.NETのbootstrapとは?概要と入手・適用方法のご紹介  (1-1) bootstrapとは?  (1-2) bootstrapの入手方法~プロジェクトへ …

  • English (United States)
  • 日本語
Top