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

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

関連記事

BundleConfig.csの設定および記述方法について

  <目次> (1) BundleConfig.csの設定および記述方法について  (1-1) BundleConfig.csの設定および記述方法について  (1-2) BundleConf …

Xamarin.FormsでHelloworldする手順+Buttonコントロール追加のサンプルコード紹介

<目次> (1) Xamarin.FormsでHelloworldする手順  (1-1) Xamarin.Formsプロジェクト構成の概要  (1-2) MainPage.xamlの修正  (1-3) …

C#でファイルの存在チェックを行う方法+サンプルプログラムをご紹介

<目次> (1) C#でファイルの存在チェックを行う方法  (1-1) 構文  (1-2) サンプルプログラム (1) C#でファイルの存在チェックを行う方法 (1-1) 構文 (構文) if (!F …

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

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

C#で型をStringからintに変更する方法~TryParseメソッドによる型変換~

<目次> (1) C#で型をStringからintに変更する方法  (1-1) 構文  (1-2) サンプルプログラム  (1-3) プログラム補足「'{0}’や'{1}’」に …

  • English (United States)
  • 日本語
Top