2012-02-09 5 views
7

Я пытаюсь интегрировать программное обеспечение RedBack SQLBackup Pro в свое собственное программное обеспечение для резервного копирования, написанное на C#. Естественный способ сделать это через их Extended Stored Procedure. Проблемы в том, что она называется в формате я никогда не видел раньше:Как вызвать хранимую процедуру с нетрадиционными параметрами?

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

Моя вторая попытка немедленно возвращает и появляется (на 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); 

Моя третья попытка также, похоже, удастся, но резервное копирование не на самом деле принято:

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

Что мне не хватает?

UPDATE 1:

я проглядел документации Red Gate, который говорит, что ХП не будет на самом деле поднять ошибку SQL, он просто возвращает ошибки в выходной таблице. Slick. Это может объяснить, почему во втором и третьем тестах я получил молчание при неудачах: некоторые основные проблемы, и они не собирают результаты, чтобы показать, почему.

Вот где я сейчас:

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 Backup.

Команда пуста.

Значит, он не видит пустого имени paramater.

Update 2:

Захватив выше в след показывает, что строка пустой параметр заканчивается заменен @Parameter1=, который объясняет, почему хранимая процедура не видит.

+0

сделать sp_help на sqlbackup, я уверен, что param имеет имя –

+0

'sp_help sqlbackup' включает только столбцы Name, Owner, Type и Created_datetime. Хотя тип «расширенный хранимый процесс» не содержит столбца param_order (или как его называют) ... –

+0

Я открыл случай с красными воротами, чтобы узнать, имеет ли этот параметр имя. Посмотрим. –

ответ

2

Это грубое и не совсем то, что я хотел, но это то, что у меня работает в настоящее время:

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 генерируется моим кодом, поэтому меня не беспокоят инъекции. Это просто ... ну, посмотри на это. Уродство.

2

Ваша первая попытка выглядит почти правильно. Я замечаю, что вам не удалось избежать обратных косых черт. Для такого рода вещей часто проще использовать префикс @, чтобы отключить экранирование строки. Кроме того, вы хотите, чтобы предварять с Exec и сделать его CommandType.Text:

EDIT: фиксированным моя собственное Escaping ошибки здесь

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

Извините, обратные косые черты на самом деле были сбежаны, но это не произошло в вопросе. Я решил избегать их, а не использовать синтаксис @ @ "", потому что кавычки были уже самой запутанной частью, и пути (как только это выяснится) будут вставлены через параметры или (бог запретить) форматирование строк. –

+0

Вы пытались добавить exec, как я уже упоминал? –

+0

Да. Тот же результат, что и # 2 и # 3: немедленно возвращается без выполнения каких-либо работ, но не работает. –

0

Вы пытались создать типичную хранимую процедуру, которая вызывает расширенную хранимую процедуру, и вызов, что от кода?Похоже, у вас есть только несколько параметров, чтобы справиться здесь.

+0

Я уверен, что это сработает, но не очень масштабируемое решение, так как эта хранимая процедура должна быть создана и управляться на каждом из моих SQL-серверов. –

+0

Не расширенная хранимая процедура на каждом сервере? Что вы подразумеваете под «управляемым»? – ScottE

+0

Расширенная хранимая процедура является частью программного пакета с сетевым установщиком, который позволяет тривиально подталкивать его и обновлять его по сети. Я не говорю, что это невозможно с помощью хранимой процедуры, но я предпочел бы просто заставить мой код работать с тем, что уже существует. –

0

У вас было несколько проблем в тестах.

В первом вы установили CommandType.StoredProcedure. Вы должны были установить его на CommandType.Text, чтобы он был достаточно умен, чтобы просто передать эту строку, чтобы быть exec'd.

В последующих примерах вы фактически не указали параметр имя. Перейдите посмотреть их процедуру SqlBackup и посмотрите, какие имена параметров. Затем используйте его. В противном случае ему ничего не будет присвоено.

+0

Обе эти проблемы объясняются в моем вопросе. Первое: «Моя первая попытка не работает, потому что она интерпретирует всю строку cmd как имя хранимой процедуры и выдает ошибку. Не удается найти хранимую процедуру« ». Моя третья попытка - это именно так, но резервная копия молча провалилась. Во-вторых, см. Мои комментарии по моему вопросу. Параметр не имеет зарегистрированного имени. –

+0

@ sh-beta: вы можете проверить proc, чтобы определить имена параметров. Нет необходимости в документации. Даже зашифрованные procs расскажут вам, что такое имена параметров. В студии управления вы можете расширить хранимое определение proc и посмотреть список параметров. Или вы можете просто щелкнуть правой кнопкой мыши по файлу proc и сценарию, чтобы вы могли получить имя параметра. – NotMe

+0

этот не дает ничего полезного. Все сценарийное определение: «EXEC dbo.sp_addextendedproc N'sqlbackup», «» –

Смежные вопросы