【问题标题】:Problem with handling COM events in VB.NET在 VB.NET 中处理 COM 事件的问题
【发布时间】:2009-06-07 13:19:53
【问题描述】:

我正在从 VB.NET 调用 SQLDMO 8.0 COM 库(使用我用 tlbimp 生成的 PIA),以便通过百分比完成通知备份数据库:

Dim server As SQLDMO.SQLServer = Nothing
Dim backup As SQLDMO.Backup = Nothing
Dim restore As SQLDMO.Restore = Nothing
Dim backupAbortable As Boolean
Dim restoreAbortable As Boolean
Try
    server = New SQLDMO.SQLServer
    server.LoginSecure = True
    server.Connect(serverName)

    backup = New SQLDMO.Backup
    backup.Action = SQLDMO.SQLDMO_BACKUP_TYPE.SQLDMOBackup_Database
    backup.BackupSetDescription = "test"
    backup.BackupSetName = "test"
    backup.Database = databaseName
    backup.Files = TransactSqlName.Delimit(fileName)
    backup.TruncateLog = SQLDMO.SQLDMO_BACKUP_LOG_TYPE.SQLDMOBackup_Log_Truncate
    backup.PercentCompleteNotification = 1
    AddHandler backup.PercentComplete, AddressOf OnOperationPercentComplete
    AddHandler backup.NextMedia, AddressOf OnOperationNextMedia
    AddHandler backup.Complete, AddressOf OnOperationComplete
    backupAbortable = True
    backup.SQLBackup(server)
    backupAbortable = False

    restore = New SQLDMO.Restore
    restore.Files = backup.Files
    AddHandler restore.PercentComplete, AddressOf OnOperationPercentComplete
    AddHandler restore.NextMedia, AddressOf OnOperationNextMedia
    AddHandler restore.Complete, AddressOf OnOperationComplete
    restoreAbortable = True
    restore.SQLVerify(server)
    restoreAbortable = False

    server.DisConnect()
Catch ex As AbortException
    If backupAbortable Then
        backup.Abort()
    End If
    If restoreAbortable Then
        restore.Abort()
    End If
Finally
    If restore IsNot Nothing Then
        RemoveHandler restore.PercentComplete, AddressOf OnOperationPercentComplete
        RemoveHandler restore.NextMedia, AddressOf OnOperationNextMedia
        RemoveHandler restore.Complete, AddressOf OnOperationComplete
        Marshal.FinalReleaseComObject(restore)
        restore = Nothing
    End If
    If backup IsNot Nothing Then
        RemoveHandler backup.PercentComplete, AddressOf OnOperationPercentComplete
        RemoveHandler backup.NextMedia, AddressOf OnOperationNextMedia
        RemoveHandler backup.Complete, AddressOf OnOperationComplete
        Marshal.FinalReleaseComObject(backup)
        backup = Nothing
    End If
    If server IsNot Nothing Then
        Marshal.FinalReleaseComObject(server)
        server = Nothing
    End If
End Try

除了事件处理程序之外,这工作正常 - 只有第一个连接的事件处理程序实际执行。我不能肯定地说 NextMedia 事件,因为它只为磁带备份触发,但至于其他两个,我要么得到 Complete 事件,要么触发 PercentComplete 事件,具体取决于 AddHandler 语句的顺序,从不同时在同一时间。

可能性:

  1. 我做错了(欢迎提出建议!)
  2. SQLDMO 8.0 中存在一个错误,它实际上只触发了其中一个事件。
  3. RCW 或 VB.NET 编译器中存在影响 COM 互操作事件的错误。

有什么想法吗?

【问题讨论】:

  • sqldmo.dll文件版本为2000.85.2312.0,typelib版本为8.0。运行代码的 SQL Server 版本可以是 2000 或 2005。我最好去仔细检查两个版本是否发生了相同的行为。
  • 抱歉,typelib 版本是 8.5。似乎 SQL 2005 升级了我原来的 SQL 2000 安装。 :-)
  • 是的,两个版本都发生了相同的行为。

标签: .net sql-server vb.net interop


【解决方案1】:

这适用于 VB.NET 2005,不确定 1.1。

我知道您在 COM 互操作方面做了很多工作,但您能否只使用连接之外的信息事件

注意 STATS = 10.. 这意味着每 10% 提供一次进度通知

这只是我一直在做的一个项目的一个sn-p,我希望你能从中得到你需要的东西。

public sub Backup()
  Dim Conn As SqlClient.SqlConnection
  dim theCommand as SqlClient.SQLCommand
  Conn = New SqlClient.SqlConnection("Data Source=.\MyInstance;Initial Catalog=Master;Integrated Security=SSPI;")
  theCommand = Conn.CreateCommand

  theCommand.CommandText = "BACKUP DATABASE [MyDatabase] TO DISK = '" & mDatabasePath & "\" & Filenames.SQLBackup & "' WITH NOFORMAT, INIT, NAME = 'MyDatabase-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10"

  AddHandler Conn.InfoMessage, AddressOf onSqlInfoMessage
  'make sure the events are fired as they are available, instead of at the end.
  Conn.FireInfoMessageEventOnUserErrors = True

  Conn.Open()

  theCommand.ExecuteNonQuery()
      RemoveHandler Conn.InfoMessage, AddressOf onSqlInfoMessage

  Conn.Close()

end sub 

   Private Sub onSqlInfoMessage(ByVal sender As Object, ByVal args As SqlClient.SqlInfoMessageEventArgs)
        If args.Message.EndsWith("percent processed.") Then
            Dim theMatch As System.Text.RegularExpressions.Match
            theMatch = mRegEx.Match(args.Message)
            debug.print("Progress = " & theMatch.Value.Trim)
        End If
    End Sub

【讨论】:

  • 谢谢 Paul,我不知道 FireInfoMessageEventOnUserErrors 属性。这是一个比使用 SQLDMO 更好的解决方案,并且我已将所有备份/恢复代码转换回 ADO.NET。好一个。 :-)
猜你喜欢
  • 1970-01-01
  • 2019-06-16
  • 1970-01-01
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
  • 2019-08-03
  • 1970-01-01
相关资源
最近更新 更多