2012-02-09 7 views
7

Próbuję zintegrować oprogramowanie SQLBackup Pro Red Gate z moim wewnętrznym oprogramowaniem do tworzenia kopii zapasowych, napisanym w języku C#. Naturalnym sposobem na to jest ich Extended Stored Procedure. Problem polega na tym, że jest wywoływany w formacie, którego nigdy wcześniej nie widziałem:Jak wywołać procedurę składowaną o niekonwencjonalnych parametrach?

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

Działa to dobrze, gdy jest uruchamiany przez SSMS. Tam, gdzie napotkasz problemy, próbuje wywołać to z C# (używając .NET 4 i Dapper Dot Net).

Moja pierwsza próba nie działa ponieważ interpretuje całą cmd ciąg jako nazwę procedury przechowywanej i wyrzuca błąd „nie można odnaleźć procedury przechowywanej«»”:

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

Moja druga próba natychmiast powraca i pojawia się (C#), aby odnieść sukces, ale nie kopia zapasowa jest rzeczywiście podjęte (to jest do bani również dla parametryzacji):

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

Moja trzecia próba wydaje się również, aby odnieść sukces, ale nie kopia zapasowa jest rzeczywiście zrobione:

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

Czego mi brakuje?

UPDATE 1:

przeoczyłem dokumentację Red Gate, który mówi, że nie będą przechowywane proc rzeczywiście podnieść błąd SQL, po prostu zwraca błędy w tabeli wyjściowej. Przysiek. To może wyjaśnić, dlaczego miałem cichą awarię w drugim i trzecim teście powyżej: jakiś podstawowy problem i nie zbierają danych wyjściowych, aby pokazać dlaczego.

Oto gdzie jestem teraz:

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

Kiedy uruchomić tego i sprawdzić te parametry wyjściowe, mam kod Exit 870:

No przekazany do polecenia SQL kopii zapasowej.

Polecenie jest puste.

Tak więc nie widzimy pustego nazwanego paramateru.

Aktualizacja 2:

Przechwytywanie wyżej w ślad wskazuje, że parametr pusty ciąg kończy się zastąpić @Parameter1= co wyjaśnia, dlaczego procedura przechowywana nie widzi.

+0

zrobić sp_help na sqlbackup, jestem pewien, że param ma nazwę –

+0

'sp_help sqlbackup' zawiera tylko kolumny Nazwa, Właściciel, Typ i Created_datetime. Mimo że typ jest "rozszerzonym procem przechowywanym", nie ma kolumny "param_order" (lub jak tam się nazywa) ... –

+0

Otworzyłem skrzynkę z czerwoną bramą, aby sprawdzić, czy ten parametr ma nazwę. Zobaczymy. –

Odpowiedz

2

To brutto, a nie w ogóle, co chciałem, ale to, co mam teraz pracuje:

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

ten wykonuje kopię zapasową i faktycznie zwraca stan awarii, która narażona jest podstawowy problem, który spowodował uszkodzić część cichych awarii.

Przed uruchomieniem, myDbName jest sprawdzane na liście znanych baz danych, aby upewnić się, że istnieje, a moja ścieżka jest generowana przez mój kod, więc nie martwię się o zastrzyki. Po prostu ... no cóż, popatrz na to. Ohydny.

2

Twoja pierwsza próba wygląda prawie prawidłowo. Zauważyłem, że nie udało ci się uciec od ukośników. W przypadku takich rzeczy często łatwiej jest użyć przedrostka @ do wyłączenia funkcji escape dla ciągu znaków. Również chcesz poprzedzić z exec i uczynić go CommandType.Text:

EDIT: Fixed moje własne błędy Ucieczki tutaj

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

Niestety, odwrócone ukośniki faktycznie uciekły, ale nie doszło do tego w pytaniu. Wybrałem ucieczkę, zamiast używać składni "@" ", ponieważ cytaty były już najbardziej zagmatwaną częścią, a ścieżki (po tym, jak się to zorientuje) będą wstawiane za pomocą parametrów lub (hałaśliwa broń) formatowania napisów. –

+0

Czy próbowałeś dodać exec, o którym wspomniałem? –

+0

Tak. Ten sam wynik co # 2 i # 3: zwraca natychmiast, bez wykonywania jakiejkolwiek pracy, ale wygląda na to, że nie działa. –

0

Czy próbowałeś tworząc typową procedurę przechowywaną, która wywołuje rozszerzona procedura przechowywana, a nazywając że z kodu?Wygląda na to, że masz tutaj tylko kilka parametrów.

+0

Jestem pewien, że to zadziała, ale nie jest to rozwiązanie skalowalne, ponieważ procedura składowana, o której mowa, musiałaby zostać utworzona i zarządzana na każdym z moich serwerów SQL. –

+0

Czy rozszerzona procedura składowana nie jest na każdym serwerze? Co masz na myśli przez "zarządzany"? – ScottE

+0

Rozszerzona procedura składowana jest częścią pakietu oprogramowania z instalatorem sieciowym, który pozwala na trywialne przesuwanie go i aktualizowanie go w sieci. Nie mówię, że jest to niemożliwe w przypadku procedury przechowywanej, ale wolałbym, aby mój kod działał z tym, co już istnieje. –

0

Podczas testów masz kilka problemów.

W pierwszym ustawiono CommandType.StoredProcedure. Powinieneś ustawić go na CommandType.Text, tak aby był wystarczająco inteligentny, aby po prostu przekazać ten ciąg, aby był wykonywany.

W kolejnych przykładach nie nadano temu parametrowi nazwy. Zobacz swoją procedurę SqlBackup i zobacz, jakie są nazwy parametrów. Następnie użyj go. W przeciwnym razie nic nie zostanie do niej przypisane.

+0

Oba te problemy są wyjaśnione w moim pytaniu. Pierwsza: "Moja pierwsza próba nie działa, ponieważ interpretuje cały łańcuch cmd jako nazwę procedury przechowywanej i zgłasza błąd Nie można znaleźć procedury przechowywanej" "". Moja trzecia próba jest właśnie taka, ale kopia zapasowa w milczeniu zawiodła. Po drugie, zobacz moje komentarze na moje pytanie. Parametr nie ma udokumentowanej nazwy. –

+0

@ sh-beta: możesz sprawdzić proces, aby określić nazwy parametrów. Nie ma potrzeby dokumentacji. Nawet zaszyfrowane procenty powie Ci, jakie są nazwy parametrów. W studio zarządzania możesz rozwinąć zapisaną definicję proc i przejrzeć listę parametrów. Możesz też kliknąć prawym przyciskiem myszy na proc i skrypować go, aby uzyskać nazwę parametru. – NotMe

+0

ten nie daje nic użytecznego. Cała definicja skryptu to "EXEC dbo.sp_addextendedproc N'sqlbackup", "'" –