前提・実現したいこと
現在、とあるデータを管理するシステムを作成しているのですが、使用するユーザーが任意のタイミングでバックアップ、リストアを行うことができる機能を追加したいと思っています。
バックアップファイルはクライアント側に保存し、リストア時にクライアントからファイルを選択し、そのファイルの内容をサーバーのDBに書き込むという処理を行いたいと思っています。
実際に作成しており、バックアップをクライアントに保存することには成功したのですが、サーバーへのリストア時にエラーが発生してしまい、上手くいきません。
発生している問題・エラーメッセージ
例外がスローされました: 'System.Exception' (mscorlib.dll の中) System.Exception: Received unexpected backend message CopyInResponse. Please file a bug. 場所 Npgsql.NpgsqlConnector.UnexpectedMessageReceived(BackendMessageCode received) 場所 Npgsql.NpgsqlDataReader.<NextResult>d__44.MoveNext() --- 直前に例外が・Xローされた場所からのスタック トレースの終わり --- 場所 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 場所 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 場所 Npgsql.NpgsqlDataReader.NextResult() 場所 Npgsql.NpgsqlCommand.<ExecuteReader>d__105.MoveNext() --- 直前に例外がスローされた場所からのスタック トレースの終わり --- 場所 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 場所 Npgsql.NpgsqlCommand.<ExecuteReader>d__105.MoveNext() --- 直前に例外がスローされた場所からのスタック トレースの終わり --- 場所 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 場所 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 場所 Npgsql.NpgsqlCommand.<ExecuteNonQuery>d__93.MoveNext() --- 直前に例外がスローされた場所からのスタック トレースの終わり --- 場所 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 場所 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 場所 Npgsql.NpgsqlCommand.ExecuteNonQuery()
ソースコード
C#
1//バックアップを行う処理 2private void backup_Button(object sender, RoutedEventArgs e) 3 { 4 var hostNameOrIpAddr = "192.168.--.---"; 5 var portNo = 22; 6 var userName = "root"; 7 var passWord = "***"; 8 try 9 { 10 // 接続情報 11 // SSHクライアント生成 12 ConnectionInfo info = new ConnectionInfo(hostNameOrIpAddr, portNo, userName, 13 new AuthenticationMethod[] { 14 new PasswordAuthenticationMethod(userName, passWord) 15 } 16 ); 17 SshClient ssh = new SshClient(info); 18 ssh.Connect(); 19 20 if (ssh.IsConnected) 21 { 22 var cmd = ssh.RunCommand("pg_dump -U postgres test"); 23 var output = cmd.Result; 24 System.Windows.Forms.SaveFileDialog dlg = new System.Windows.Forms.SaveFileDialog(); 25 dlg.FileName = "バックアップ.txt"; 26 dlg.InitialDirectory = @"C:\"; 27 dlg.Title = "保存先のファイルを選択してください"; 28 dlg.RestoreDirectory = true; 29 dlg.OverwritePrompt = true; 30 dlg.CheckPathExists = true; 31 if (dlg.ShowDialog() == DialogResult.OK) 32 { 33 string filename = dlg.FileName; 34 Encoding enc = Encoding.GetEncoding("UTF-8"); 35 try 36 { 37 File.WriteAllText(filename, output, enc); 38 } 39 40 catch (Exception ex) 41 { 42 System.Windows.MessageBox.Show(ex.Message); 43 return; 44 } 45 } 46 47 } 48 else 49 { 50 // 接続に失敗した(未接続状態である) 51 System.Windows.MessageBox.Show("接続に失敗しました"); 52 return; 53 } 54 55 // 接続終了 56 ssh.Disconnect(); 57 } 58 catch (Exception ex) { Console.WriteLine(ex); } 59 }
C#
1private void restore_button(object sender, RoutedEventArgs e) 2 { 3 string path; 4 System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog(); 5 if (ofd.ShowDialog() == DialogResult.OK) 6 { 7 System.IO.Stream stream; 8 stream = ofd.OpenFile(); 9 path = ofd.FileName; 10 if (stream != null) 11 { 12 System.IO.StreamReader sr = 13 new System.IO.StreamReader(stream); 14 //上記のプログラムで作成したバックアップファイルを選択し、変数sqlへ 15 //sqlの内容は下に書いています。 16 sql = sr.ReadToEnd(); 17 sr.Close(); 18 stream.Close(); 19 } 20 } 21 string conn_str = "Server=198.162.--.--;Port=5432;User ID=postgres;Database=test;Password=***;Enlist=true"; 22 using (NpgsqlConnection conn = new NpgsqlConnection(conn_str)) 23 { 24 conn.Open(); 25 using (NpgsqlCommand command = new NpgsqlCommand(@sql, conn)) 26 { 27 try {command.ExecuteNonQuery(); 28 System.Windows.MessageBox.Show("リストアが完了しました"); 29 } 30 catch (System.Exception ex) 31 { Console.WriteLine(ex); } 32 } 33 conn.Close(); 34 } 35 }
txt
1//バックアップで生成された、リストアを行うファイル 2-- 3-- PostgreSQL database dump 4-- 5 6-- Dumped from database version 10.15 7-- Dumped by pg_dump version 10.15 8 9SET statement_timeout = 0; 10SET lock_timeout = 0; 11SET idle_in_transaction_session_timeout = 0; 12SET client_encoding = 'UTF8'; 13SET standard_conforming_strings = on; 14SELECT pg_catalog.set_config('search_path', '', false); 15SET check_function_bodies = false; 16SET xmloption = content; 17SET client_min_messages = warning; 18SET row_security = off; 19 20-- 21-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: 22-- 23 24CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; 25 26 27-- 28-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: 29-- 30 31COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; 32 33 34SET default_tablespace = ''; 35 36SET default_with_oids = false; 37 38 39CREATE TABLE public.master ( 40 41 id integer NOT NULL 42); 43 44 45ALTER TABLE public.master OWNER TO postgres; 46 47 48COPY public.master (id) FROM stdin; 491 50. 51 52ALTER TABLE ONLY public.master 53 ADD CONSTRAINT key PRIMARY KEY (id);
試したこと
どこが原因なのか調べていくうちに
COPY public.master (id) FROM stdin; 1 .
の部分を削除することで正常に動作するということが分かりました。
クライアントからこのコピー句を使うことはできないのでしょうか?
出来るだけバックアップファイル(SQL文)は変更しない状態で実行したいです。