どのように私は慣習的でないパラメータを持つストアドプロシージャを呼び出すのですか?

c# dapper sql-server stored-procedures

質問

Red GateのSQLBackup ProソフトウェアをC#で書かれた社内のバックアップソフトウェアに統合しようとしています。これを行うための自然な方法は、 拡張ストアドプロシージャを使用することです。問題は以前に見たことのない形式で呼ばれているということです。

master..sqlbackup '-SQL "BACKUP DATABASE pubs TO DISK = [C:\Backups\pubs.sqb]"'

これはSSMS経由で実行するとうまく動作します。私が問題に遭うところは、C#(.NET 4とDapper Dot Netを使用)から呼び出すことです。

私の最初の試行は、ストアドプロシージャの名前としてcmd文字列全体を解釈し、 "ストアドプロシージャを見つけることができません ''というエラーをスローするため動作しません:

var cmd = "master..sqlbackup '-SQL \"BACKUP DATABASE pubs TO DISK = [C:\\Backups\\pubs.sqb]\"'";
connection.Execute(cmd, commandType: CommandType.StoredProcedure, commandTimeout: 0);

私の2回目の試みはすぐに戻り、(C#に)成功するように見えますが、実際にはバックアップは取られません(これもパラメータ化にはうってつけです):

var cmd = "master..sqlbackup";
var p = new DynamicParameters();
p.Add("", "'-SQL \"BACKUP DATABASE pubs TO DISK = [C:\\Backups\\pubs.sqb]\"'");
connection.Execute(cmd, p, commandType: CommandType.StoredProcedure, commandTimeout: 0);

3回目の試行も成功したようですが、実際にバックアップは取られません。

var cmd = "master..sqlbackup '-SQL \"BACKUP DATABASE pubs TO DISK = [C:\\Backups\\pubs.sqb]\"'";
connection.Execute(cmd, commandTimeout: 0);

私は何が欠けていますか?

更新1:

私は、格納されたprocが実際にSQLエラーを発生させないというRed Gateのドキュメントを見落としました。出力テーブルにエラーが返されるだけです。スリック。これは、上記の2番目と3番目のテストで何故私が静かに失敗したのかを説明するかもしれません。いくつかの根本的な問題です。

私は今どこにいるのですか?

var cmd = "master..sqlbackup";
var p = new DynamicParameters();
p.Add("", "'-SQL \"BACKUP DATABASE pubs TO DISK = [C:\\Backups\\pubs.sqb]\"'");
p.Add("@exitcode", DbType.Int32, direction: ParameterDirection.Output);
p.Add("@sqlerrorcode", DbType.Int32, direction: ParameterDirection.Output);
connection.Execute(cmd, p, commandType: CommandType.StoredProcedure, commandTimeout: 0);

これらを実行して出力パラメータをチェックすると、終了コード870が表示されます。

SQLバックアップに渡されるコマンドはありません。

コマンドは空です。

だから、それは空の名前のパラメタを見ていない。

アップデート2:

上記のトレースをキャプチャすると、空のパラメータ文字列が@Parameter1=置き換えられ、ストアドプロシージャがそれを認識できない理由が説明されます。

受け入れられた回答

それは総体であり、私が望んでいたものではありませんが、これは私が今働いているものです:

var cmd = String.Format(@"
DECLARE @exitcode int; 
DECLARE @sqlerrorcode int;
EXEC master..sqlbackup '-SQL \"BACKUP DATABASE [{0}] TO DISK = [{1}])\"', @exitcode OUTPUT, @sqlerrorcode OUTPUT;
IF (@exitcode >= 500) OR (@sqlerrorcode <> 0)
BEGIN
RAISERROR('SQLBackup failed with exitcode %d and sqlerrorcode %d ', 16, 1, @exitcode, @sqlerrorcode)
END
", myDbName, myBkpPath);

connection.Execute(cmd, commandTimeout: 0);

これにより、バックアップが実行され、実際に障害の状態が返され、障害の原因となった根本的な問題が明らかになりました。

それが実行される前に、myDbNameが既知のデータベースのリストと照合されて存在することを確認し、myBkpPathが自分のコードによって生成されるので、私は注射について心配していません。それはちょうど...まあ、それを見てください。恐ろしいです。


人気のある回答

あなたの最初の試みはほぼ正しいように見えます。私が気づくのは、あなたがバックスラッシュから脱出しなかったことです。このような場合、@接頭辞を使用して文字列のエスケープを無効にするほうが簡単です。また、execを前に付けてCommandType.Textしたいとします:

編集:ここで自分のエスケープバグを修正

var cmd = @"exec 'master..sqlbackup -SQL ""BACKUP DATABASE pubs TO DISK = [C:\Backups\pubs.sqb]""'";
connection.Execute(cmd, commandType: CommandType.Text, commandTimeout: 0);


ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ