C#でNpgsqlを使ってPostgreSQLへアクセス【Transaction】

2021/09/21

C# Npgsql

アイキャッチ

トランザクションはあまり多くの説明は必要としないかと思われますのでサクッとやってしまいます。

どちらかと言えばロールバックが発生した後の処理をどうするかが悩ましい所かもしれません。

私の作成するサンプルソースファイルは

今回のサンプルソースは

  1. データベーステーブルを作成する
  2. データを2つINSERTする

として、この2つの処理後にコミットしてみます。

using NpgsqlConnection con = new("Server=127.0.0.1; Port=5432; User Id=test_user; Password=pass; Database=db_PostgreTest; SearchPath=public");
con.Open();
// con.Open()前に行うと例外「InvalidOperationException」になる。
using NpgsqlTransaction tran = con.BeginTransaction();
try
{
    using NpgsqlCommand cmd = new("CREATE TABLE data(id serial PRIMARY KEY, time timestamp DEFAULT clock_timestamp(), name text, numeric integer)", con);
    _ = cmd.ExecuteNonQuery();
    // データを2つINSERTする
    cmd.CommandText = "INSERT INTO data(name, numeric) VALUES ('a', 1);";
    int result1 = cmd.ExecuteNonQuery();
    cmd.CommandText = "INSERT INTO data(name, numeric) VALUES ('b', 2);";
    int result2 = cmd.ExecuteNonQuery();
    tran.Commit();
    // Commitメソッドが実行(成功)した後にRollbackメソッドを実行しても例外「InvalidOperationException」になる。
    //tran.Rollback();
}
catch (PostgresException)
{
    tran.Rollback();
}

上記4行目がトランザクションの生成ですが、注意する点としてはNpgsqlConnectionのOpenメソッド実行後になる事です。

Openメソッド実行前にトランザクションを生成すると例外「InvalidOperationException」が発生します。

実際、データベーステーブルがどのタイミングで生成されているかプログラムをステップ実行して確認してみます。

上記サンプルプログラムをステップ実行で13行目までを実行しpgAdmin4で確認した結果は

「テーブル」文字の左に「>」がなく、配下には何も存在していない事が確認できます。

つまりそれまでに記述したCREATE TABLEやINSERTがまだ実行されてないのが分かります。

この状態14行目のCommitメソッドを実行しpgAdmin4のテーブルにマウスカーソルを合わせ「右クリック」-「再読み込み」を行い「テーブル」のツリーを展開するとテーブルが存在している事が確認できます。

もし例外が発生して正しくCREATE TABLEやINSERTが実行されなかった場合はRollbackメソッドを実行し、その後はイレギュラー時に必要な処理を追記してください。

ちなみにトランザクションのCommitメソッドが正常に終了したあとに「やっぱりやめた」のRollbackメソッドは例外「InvalidOperationException」が発生して正しく処理されません。

あまり使わないかもしれませんが、こんな手法もあります。

using NpgsqlConnection con = new("Server=127.0.0.1; Port=5432; User Id=test_user; Password=pass; Database=db_PostgreTest; SearchPath=public");
con.Open();
// con.Open()前に行うと例外「InvalidOperationException」になる。
using NpgsqlTransaction tran = con.BeginTransaction();
try
{
    using NpgsqlCommand cmd = new("CREATE TABLE data(id serial PRIMARY KEY, time timestamp DEFAULT clock_timestamp(), name text, numeric integer)", con);
    cmd.Transaction = tran;
    _ = cmd.ExecuteNonQuery();
    // データをINSERTする
    cmd.CommandText = "INSERT INTO data(name, numeric) VALUES ('a', 1);";
    int result1 = cmd.ExecuteNonQuery();
    cmd.CommandText = "INSERT INTO data(name, numeric) VALUES ('b', 2);";
    int result2 = cmd.ExecuteNonQuery();
    cmd.Transaction.Commit();
}
catch (PostgresException)
{
    tran.Rollback();
}

NpgsqlCommandのTransactionプロパティに入れておき、そのTransactionプロパティのCommitメソッドを実行すると同じ動作になります。

自己紹介

自分の写真



新潟県のとある企業で働いてます。
【できる事】
電子回路設計
基板パターン設計
マイコンプログラム
C#(WinForms WPF)を使ったWindowsアプリケーション作成
PLCラダー
自動化装置アドバイザー
にほんブログ村 IT技術ブログ ソフトウェアへ

カテゴリ

このブログを検索

QooQ