在VB.NET中恢复SQL Server LocalDB时遇到会话占用异常如何解决
异常产生原因
报错的核心原因是要恢复的目标数据库正被你当前的数据库连接占用:
- 你代码中使用的全局连接对象
con,默认连接的就是要恢复的RestoDB数据库,SQL Server不允许对正在被会话访问的数据库执行恢复操作 - 执行RESTORE命令要求当前连接必须切换到
master系统数据库下操作,你直接用连接业务库的会话执行恢复命令,不符合SQL Server的操作规范
修复后的完整代码
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 Cursor = Cursors.WaitCursor ' 先关闭所有已打开的业务库连接,避免占用 If con IsNot Nothing AndAlso con.State = ConnectionState.Open Then con.Close() End If Try ' 新建连接到master系统库的连接,专门用于执行恢复操作 Using masterCon As New SqlConnection("Data Source=(LocalDB)\v11.0;Initial Catalog=master;Integrated Security=True;Connect Timeout=30") masterCon.Open() ' 先踢掉所有占用目标库的会话,再执行恢复,最后恢复多用户模式 Dim restoreSql = "ALTER DATABASE [RestoDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; RESTORE DATABASE [RestoDB] FROM DISK = @BackupPath WITH REPLACE, RECOVERY; ALTER DATABASE [RestoDB] SET MULTI_USER;" Using cmd As New SqlCommand(restoreSql, masterCon) ' 用参数化传参,避免SQL注入和路径特殊字符问题 cmd.Parameters.AddWithValue("@BackupPath", ofd.FileName) cmd.ExecuteNonQuery() End Using End Using MsgBox("Restore complete") Catch ex As Exception MsgBox("恢复失败:" & ex.Message) Finally ' 无论成功失败都还原光标状态,重新初始化业务库连接 Cursor = Cursors.Default ' 此处可添加你原有全局con连接的初始化逻辑,恢复业务库正常访问 If con IsNot Nothing Then con.Open() End Try End Sub
关键调整说明
- 恢复操作执行前先关闭所有已经打开的业务库连接,从根源避免自身连接占用目标库的问题
- 新建专门指向
master系统库的连接执行恢复命令,符合SQL Server恢复操作的要求 - 增加了
SET SINGLE_USER WITH ROLLBACK IMMEDIATE命令,强制踢掉所有其他占用目标库的会话,避免第三方程序占用导致恢复失败 - RESTORE命令增加
WITH REPLACE参数,允许覆盖已存在的数据库文件,避免本地库已存在时恢复失败 - 使用参数化查询传递备份文件路径,避免SQL注入风险,同时解决路径包含单引号等特殊字符时的执行错误
- 增加异常捕获逻辑,无论操作成功失败都统一还原光标状态,避免报错后界面一直处于等待状态
内容的提问来源于stack exchange,提问作者Chaker
相关产品推荐
相关产品推荐

