【问题标题】:Restore SQL Server localdb in vb.net在 vb.net 中恢复 SQL Server localdb
【发布时间】:2022-01-05 02:36:40
【问题描述】:

我想恢复一个 SQL Server localdb 数据库。我试过这段代码:

Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    Dim ofd As New OpenFileDialog() With
        {
            .Filter = "Backup file | *.bak",
            .FileName = ""
        }

    If ofd.ShowDialog = System.Windows.Forms.DialogResult.OK Then
            Cursor = Cursors.WaitCursor
            Dim csb = New SqlConnectionStringBuilder("Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\CHAKER\Documents\RestoDB.mdf;Integrated Security=True;Connect Timeout=30")
            Dim dbFullPath = csb.AttachDBFilename

            Dim sql = String.Format("RESTORE DATABASE ""{0}"" From DISK = '{1}'", dbFullPath, ofd.FileName)
            Dim cmd As New SqlCommand(sql, con)
            cmd.ExecuteNonQuery()
            MsgBox("Restore complete")
            Cursor = Cursors.Default

        End If

    End Sub

我得到了这个例外:

RESTORE 无法处理数据库“C:\Users\CHAKER\Documents\RestoDB.mdf”,因为该会话正在使用它。建议执行此操作时使用master数据库。

【问题讨论】:

  • 您是否尝试将“Initial Catalog=master”添加到您的连接字符串?
  • @DanGuzman 我尝试使用“Initial Catalog=master”得到同样的异常
  • 我看不到您在哪里声明和打开连接。在执行还原之前尝试con.ChangeDatabase("master")
  • 代码中所有打开数据库连接的地方都必须在使用完毕后关闭它(并在连接上调用.Dispose())。你不应该有一个全局 con 变量。您可以看到我在this answer 中的模式,虽然它使用 OleDbConnection 而不是 SqlConnection 等。
  • @AndrewMorton 我尝试 con.ChangeDatabase("master") 我得到这个异常附加信息:要恢复主数据库,服务器必须在单用户模式下运行。有关以单用户模式启动的信息,请参阅联机丛书中的“如何:启动 SQL Server 实例 (sqlservr.exe)”。

标签: sql sql-server vb.net sql-server-2012-localdb


【解决方案1】:

您的代码存在许多问题:

  • 您的主要问题:您正在按文件名恢复数据库,但您已经使用AttachDbFileName 附加了它,并且无法恢复这样的数据库。 Using AttachDbFileName is in any case deprecated. 您应该使用普通的 CREATE DATABASE FOR ATTACH 语法将其附加到 LocalDB。
  • 最好不要对连接字符串进行硬编码,而是将其存储在设置文件中。
  • 您需要使用Using 处理您的连接和命令对象。不要缓存连接对象。
  • 连接打开时不要使用 MessageBox 阻塞线程
  • 您应该在RESTORE 命令上使用参数化,而不是直接注入名称
In settings file:
ConnectionString "Data Source=(LocalDB)\v11.0;Initial Catalog=RestoDB;Integrated Security=True;Connect Timeout=30"
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    Dim ofd As New OpenFileDialog() With
        {
            .Filter = "Backup file | *.bak",
            .FileName = ""
        }

    If ofd.ShowDialog <> System.Windows.Forms.DialogResult.OK Then Exit Sub

    Try
        Cursor = Cursors.WaitCursor
        Const sql = "RESTORE DATABASE @DB From DISK = @FileName"
        Using con As New SqlConnection(Properties.ConnectionString),
              cmd As New SqlCommand(sql, con)
            cmd.Parameters.Add("@DB", SqlDbType.NVarChar, 128).Value = con.Database
            cmd.Parameters.Add("@FileName", SqlDbType.NVarChar, 255).Value = ofd.FileName
            cmd.ExecuteNonQuery()
        End Using
        MsgBox("Restore complete")
    Catch ex As Exception
        MsgBox("Error: " + ex.Message)
    Finally
        Cursor = Cursors.Default
    End Finally

End Sub

【讨论】:

  • 代码不工作
  • 你确定那里可以使用SQL参数吗?同理,列名不能是 SQL 参数。此外,Try...Catch 的语法不正确。
  • @Chaker 现在应该可以工作了。除非您遇到异常,否则是什么?
  • @AndrewMorton 谢谢,好久没写VB了。 RESTORE 的语法是 RESTORE DATABASE { database_name | @database_name_var } [ FROM &lt;backup_device&gt; [ ,...n ] ]&lt;backup_device&gt; ::= {{ logical_backup_device_name | @logical_backup_device_name_var } | { DISK | TAPE | URL } = { 'physical_backup_device_name' | @physical_backup_device_name_var }} 所以它可以被参数化,见 docs.microsoft.com/en-us/sql/t-sql/statements/…
  • @AndrewMorton 例如,这是有效代码,请参阅dbfiddle.uk/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 2012-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-22
相关资源
最近更新 更多