問題
PostgreSQLの、Npgsqlの、BeginTextImport
の処理で、Npgsql.PostgresException
の例外が発生する場合があります。その場合、データベースにも、データをインポートできません。
原因
NpgsqlConnection
を、すぐにClose
すると、例外が発生することがあるようです(しない場合もある)。
解決法
Closeしないでおけばインポートに成功します。ただし、Closeしないままで良いのかどうかわかりません。
コード例
例えば、クライアント側で、CSVファイルから、データベースにインポートするのは、次のコードになります。
conn.Open()
するので、conn.Close()
したわけですが、これだと失敗する場合があります。
var connString = "Host=localhost; Port=5432; Username=postgres; Database=HOGEDatabase;";
using var conn = new NpgsqlConnection(connString);
conn.Open();
using var writer = conn.BeginTextImport(@"COPY tablename (field_text, field_int4) FROM STDIN (FORMAT CSV , HEADER)");
using StreamReader csvReader = new(@"C:\test.csv", Encoding.UTF8);
string? str;
while ((str = csvReader.ReadLine()) != null)
{
writer.WriteLine(str);
}
//conn.Close(); //ここで例外が発生することがある
備考
- 当初、テーブルをCSVファイルにエクスポート・インポートする処理を、EntityFramework Core と、CSV Helper で行おうとしました。しかし、
jsonb
の列の処理が、大変そうだなと思われたので(検証していないので、実際はどうかはわかりません)、別の方法を探し、PostgreSQLのCOPYを利用するのが良さそうだと分かりました。 - このCOPYは、サーバー側と、クライアント側とで、使い方が違うので、混乱しますね。
2022-03-19追記。
- CSV HelperのType Conversionを利用すれば、クラスをJsonにしCSVに保存(またその逆)も問題ないことがわかり、CSV Helperを利用してインポート・エクスポートの仕組みにしました。
- PostgreSQLのCOPYは、idが一致する時置き換える仕組みがないようなので、利用を断念。
- クラスをJsonbにした時に、Jsonbに保存されるJsonの文字列を直接取り出す方法が見つからなかったので、これも断念。結局、Jsonb → EntityFrameworkCoreのクラス → CSVHelperでJsonにタイプコンバート → CSVという方法を採用しました。CSVからJsonbへはこの逆です。
参照
環境
- Npgsql 7.0.0-preview.1
- .NET 6