틀에 얽매이지 않는 매개 변수를 사용하여 저장 프로 시저를 호출하려면 어떻게해야합니까?

c# dapper sql-server stored-procedures

문제

Red Gate의 SQLBackup Pro 소프트웨어를 C #으로 작성된 사내 백업 소프트웨어에 통합하려고합니다. 이를 수행하는 자연스러운 방법은 확장 저장 프로 시저를 사용하는 것 입니다. 문제는 이전에 본 적이없는 형식으로 호출된다는 것입니다.

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

이 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 '-SQL \"BACKUP DATABASE pubs TO DISK = [C:\\Backups\\pubs.sqb]\"'";
connection.Execute(cmd, commandType: CommandType.StoredProcedure, commandTimeout: 0);

내 세 번째 시도도 성공한 것처럼 보이지만 실제로 백업은 수행되지 않습니다.

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

내가 뭘 놓치고 있니?

업데이트 1 :

저장된 proc이 실제로 SQL 오류를 발생시키지 않는다는 Red Gate 문서를 간과 했으므로 출력 테이블에 오류 만 반환합니다. 멋진. 이것은 위의 두 번째와 세 번째 테스트에서 침묵의 실패를 얻는 이유를 설명 할 수 있습니다. 일부 근본적인 문제와 그 이유를 보여주기 위해 출력을 수집하지 않습니다.

여기에 내가 지금있다 :

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

이걸 실행하고 출력 매개 변수를 확인하면 Exit Code 870이 표시됩니다.

SQL Backup으로 전달 된 명령이 없습니다.

명령이 비어 있습니다.

따라서 빈 이름의 매개 변수가 표시되지 않습니다.

업데이트 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는 합법적입니까? 예, 이유를 알아보십시오.