【问题标题】:SQL Management Object, Continue On Error yet log messageSQL 管理对象,继续出错但记录消息
【发布时间】:2010-07-23 21:14:03
【问题描述】:

我目前正在使用 SMO 来帮助自动修补和/或升级生产中的客户数据库。我正在使用以下代码

Public Sub RunScript(ByVal db As Database, ByVal scriptInfo As FileInfo)
    If scriptInfo.Exists Then

        RaiseEvent LogMessage("Executing Indicated Script: " & scriptInfo.Name)
        Using sr As New StreamReader(scriptInfo.FullName)
            Dim script As String = sr.ReadToEnd
            Try
                db.ExecuteNonQuery(script)
            Catch ex As Exception
                RaiseEvent LogMessage("ERROR: " & ex.Message.ToString)
                db.ExecuteNonQuery(script,
                                Microsoft.SqlServer.Management.Common.ExecutionTypes.ContinueOnError)
            End Try
        End Using

    End If
End Sub

我正在做的是记录SQLConnection 消息,这些消息来自我与Database 部分一起使用的SQLConneciton,这些消息为我提供了关于正在发生的事情的相当简单的消息。我是否也在通过我创建的LogMessage(string) 事件记录自己的各种消息。

我真正想做的是执行脚本,以便在出现错误时继续,但仍然记录有错误,而不必像现在这样。

原因是一些破坏交易的错误是微不足道的,它们正在发生是正常的。就像在索引存在或你有什么的时候尝试创建一个索引。

有什么方法可以在出错时继续执行脚本但仍然记录错误消息?

**编辑** 澄清进来的两个对象是什么

scriptInfo 是一个 FileInfo 对象,它告诉 StreamReader 从哪里加载 sql 脚本。

db 是一个与SQLClient.Connection 关联的SMO Database 对象,它允许我在与db 关联的数据库上执行脚本

错误记录发生在 SqlClient.SqlConnections OnInfo 事件上,或来自 LogMessage 事件

【问题讨论】:

    标签: .net sql


    【解决方案1】:

    假设您使用的是 SQL Server 2005 或更高版本,您可以为脚本中的每个语句使用不同的 TRY/CATCH 块。这是一个例子:

    DECLARE @errorLog TABLE (
      row_id INT NOT NULL IDENTITY(1,1), 
      error_msg NVARCHAR(4000)
    ) 
    
    /** Create the table **/ 
    BEGIN TRY 
      CREATE TABLE t1 (RowID INT NOT NULL) 
    END TRY 
    
    BEGIN CATCH 
      INSERT @errorLog (error_msg) 
      SELECT ERROR_MESSAGE()
    END CATCH 
    
    /** Create the table again - will raise an error message **/ 
    BEGIN TRY 
      CREATE TABLE t1 (RowID INT NOT NULL) 
    END TRY 
    
    BEGIN CATCH 
      INSERT @errorLog (error_msg) 
      SELECT ERROR_MESSAGE()
    END CATCH 
    
    /** Create the index **/ 
    BEGIN TRY 
      CREATE INDEX IX_t1 ON t1 (RowID) 
    END TRY 
    
    BEGIN CATCH 
      INSERT @errorLog (error_msg)
      SELECT ERROR_MESSAGE()
    END CATCH 
    
    /** Return the errors **/
    IF EXISTS (SELECT * FROM @errorLog) 
      SELECT error_msg FROM @errorLog
    
    /** Confirm it worked **/ 
    EXEC sp_help 't1' 
    

    此脚本将在失败后继续处理。如果存在错误,它们将在结果集中返回。因此,您需要更改原始代码,但我认为您可能无论如何都必须这样做,以便在一个脚本中容纳多个错误。

    另一方面,诸如重复索引错误之类的事情可以很容易地在脚本本身中处理(即检查对象是否已经存在)。而且由于此解决方案需要对原始脚本进行大量更改,因此这可能是一个更可取的选择。

    【讨论】:

    • 嗯,修改脚本不是问题,我们使用 CodeSmith 来生成该程序使用的大部分脚本。最后一行EXEC sp_help 't1' 是做什么的? (谷歌搜索,但答案会很好)。我们也尽可能多地使用 If Exists not exists。
    • 最后一行只是为了表明脚本在出现错误的情况下仍然有效。 sp_help 命令显示表的结构、约束和索引。
    【解决方案2】:

    您发布的只是您对其中包含的任何“scriptinfo”的执行调用。

    'scriptinfo' 的文本是什么?这就是您需要查看/内置优雅处理失败的 CRUD/事务等的地方。

    如果你能发布'scriptinfo',也许我可以给你一些想法。

    【讨论】:

      猜你喜欢
      • 2021-11-23
      • 2013-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多