Comment appeler une procédure stockée avec des paramètres non conventionnels?

c# dapper sql-server stored-procedures

Question

Je tente d'intégrer le logiciel SQLBackup Pro de Red Gate dans mon logiciel de sauvegarde interne, écrit en C #. La façon naturelle de le faire est via leur procédure stockée étendue . Le problème est que cela s'appelle dans un format que je n'ai jamais vu auparavant:

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

Cela fonctionne très bien lorsqu'il est exécuté via SSMS. Là où j'ai des problèmes, j'essaie de l'appeler depuis C # (en utilisant .NET 4 et Dapper Dot Net ).

Ma première tentative ne fonctionne pas car elle interprète l'intégralité de la chaîne cmd comme le nom de la procédure stockée et génère l'erreur "Impossible de trouver la procédure stockée":

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

Ma deuxième tentative revient immédiatement et apparaît (en C #) pour réussir, mais aucune sauvegarde n’est réellement effectuée (cela ne sert à rien pour le paramétrage):

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);

Ma troisième tentative semble également réussir, mais aucune sauvegarde n'est réellement effectuée:

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

Qu'est-ce que je rate?

MISE À JOUR 1:

J'ai négligé la documentation Red Gate qui dit que le proc stocké ne soulèvera pas d'erreur SQL, il renvoie simplement des erreurs dans une table de sortie. Nappe. Cela pourrait expliquer pourquoi j'ai eu des échecs silencieux lors des deuxième et troisième tests ci-dessus: un problème sous-jacent et ils ne collectent pas les résultats pour montrer pourquoi.

Voici où je suis maintenant:

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);

Quand je lance ceci et vérifie ces paramètres de sortie, je reçois le code de sortie 870:

Aucune commande passée à SQL Backup.

La commande est vide.

Donc, il ne voit pas le paramètre nommé vide.

Mise à jour 2:

Capturer ce qui précède dans une trace montre que la chaîne de paramètre vide est remplacée par @Parameter1= ce qui explique pourquoi la procédure stockée ne le voit pas.

Réponse acceptée

C'est dégoûtant et pas du tout ce que je voulais, mais c'est ce que je travaille maintenant:

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);

Cela exécute la sauvegarde et renvoie en fait l'état d'échec, ce qui expose un problème sous-jacent à l'origine de l'échec des défaillances en mode silencieux.

Avant de s'exécuter, myDbName est comparé à une liste de bases de données connues pour s'assurer qu'il existe et que myBkpPath est généré par mon code. Je ne m'inquiète donc pas des injections. C'est juste que ... eh bien, regarde ça. Hideux.


Réponse populaire

Votre première tentative semble presque correcte. Ce que je remarque, c'est que vous n'avez pas réussi à échapper aux barres obliques inverses. Pour ce genre de chose, il est souvent plus facile d'utiliser le préfixe @ pour désactiver l'échappement de la chaîne. De plus, vous voulez ajouter un exemple avec exec et le rendre CommandType.Text :

EDIT: corrigé ici mes propres bugs

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



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi