问题
If you execute backup using SMO, after successful completion, I test the SqlError for null, considering that the backup completed without errors:
But, as you can see, it actually return an error of class 0 number 3014 meaning success.
So the question is:
Q: How can I find out if backup completed successfully or not, and how should I handle these messages and statuses cleanly?
I'm afraid that there are multiple of "gotchas" here that I don't want to bite me in the ass later when this code goes production :)
回答1:
I agree there are multiple "gotchas" and I personally think Microsoft SMO events are poorly implemented as the ServerMessageEventArgs contains a Property Error which not always provides information about an error but messages about successful operations!!
As an example: The "error" with code 4035 is an information message. Not an error. The "error" with code 3014 is an information message that happens when completed successfully. Not an error
Also notice that the Information event does not always happen when an error has occurred. It actually happens whenever SQL Server sends a message that could be information about the operation that has finished successfully
I am also concerned about not handling the errors/success properly, but checking sqlError as Null is a bad idea since it will not be ever null and it will always contain some message about successful operation or an error. And assuming that Information event occurs when there is an error is also a bad idea.
I suggest to handle the errors through the SqlError.Number and depending on the SMO event it has been triggered.
I have made the following code to create a database backup. It is in VB.NET but in C# would be similar. It receives necessary parameters including a delegate where to invoke events (to be handled at GUI), a progress to report the percentage and error handling depending on event triggered and the SqlError.Number as mentioned
Public Sub BackupDatabase(databaseName As String, backupFileFullPath As String, optionsBackup As OptionsBackupDatabase, operationProgress As IProgress(Of Integer),
operationResult As Action(Of OperationResult)) Implements IDatabaseManager.BackupDatabase
Dim sqlBackup As New Smo.Backup()
sqlBackup.Action = Smo.BackupActionType.Database
sqlBackup.BackupSetName = databaseName & " Backup"
sqlBackup.BackupSetDescription = "Full Backup of " & databaseName
sqlBackup.Database = databaseName
Dim bkDevice As New Smo.BackupDeviceItem(backupFileFullPath, Smo.DeviceType.File)
sqlBackup.Devices.Add(bkDevice)
sqlBackup.Initialize = optionsBackup.Overwrite
sqlBackup.Initialize = True
sqlBackup.PercentCompleteNotification = 5
AddHandler sqlBackup.PercentComplete, Sub(sender As Object, e As PercentCompleteEventArgs)
operationProgress.Report(e.Percent)
End Sub
AddHandler sqlBackup.Complete, Sub(sender As Object, e As ServerMessageEventArgs)
Dim sqlMessage As SqlClient.SqlError = e.Error
Dim opResult As New OperationResult()
Select Case sqlMessage.Number
Case 3014
opResult.operationResultType = OperationResultType.SmoSuccess
opResult.message = "Backup successfully created at " & backupFileFullPath & ". " & sqlMessage.Number & ": " & sqlMessage.Message
Case Else
opResult.operationResultType = OperationResultType.SmoError
opResult.message = "ERROR CODE " & sqlMessage.Number & ": " & sqlMessage.Message
End Select
operationResult.Invoke(opResult)
End Sub
AddHandler sqlBackup.NextMedia, Sub(sender As Object, e As ServerMessageEventArgs)
Dim sqlMessage As SqlClient.SqlError = e.Error
Dim opResult As New OperationResult()
opResult.operationResultType = OperationResultType.SmoError
opResult.message = "ERROR CODE: " & sqlMessage.Number & ": " & sqlMessage.Message
operationResult.Invoke(opResult)
End Sub
AddHandler sqlBackup.Information, Sub(sender As Object, e As ServerMessageEventArgs)
Dim sqlMessage As SqlClient.SqlError = e.Error
Dim opResult As New OperationResult()
Select Case sqlMessage.Number
Case 4035
opResult.operationResultType = OperationResultType.SmoInformation
opResult.message = sqlMessage.Number & ": " & sqlMessage.Message
Case Else
opResult.operationResultType = OperationResultType.SmoError
opResult.message = "ERROR CODE " & sqlMessage.Number & ": " & sqlMessage.Message
End Select
operationResult.Invoke(opResult)
End Sub
Try
sqlBackup.SqlBackupAsync(smoServer)
Catch ex As Exception
Throw New BackupManagerException("Error backing up database " & databaseName, ex)
End Try
End Sub
回答2:
I could be wrong, but I believe that the Complete event firing is the main indicator that the backup was successful - errors would be reported through the Information event.
Since the class of the error is 0
(or any value below 10), it indicates that it's an informational message, not an actual error (Error
is somewhat misnamed). And 3014 is defined as the message that's sent when the backup is successful.
I'm not sure what other "gotchas" you're concerned with, since you haven't documented them.
来源:https://stackoverflow.com/questions/9358576/sql-server-smo-backuping-how-to-determine-failure-success