SQL Server 2012数据库恢复遇会话占用报错,如何解决?
解决SQL Server 2012数据库恢复时的会话占用报错
这个报错的核心原因很明确:你当前的数据库连接正处于要恢复的目标数据库会话中,导致RESTORE操作无法获取独占资源。按照下面的步骤修改代码就能解决:
1. 连接到master数据库而非目标数据库
你的原连接字符串直接指定了要恢复的db_datatestproject,这会让连接默认绑定到该数据库,执行恢复操作时自然会冲突。把连接目标改成master数据库(SQL Server的系统库,专门用来执行这类全局操作):
// 注意:user/password和Integrated Security二选一,不要同时配置 conString = "server=.\\SQLEXPRESS;database=master;user=admin;password=123;"; // 或者用Windows身份验证: // conString = "server=.\\SQLEXPRESS;database=master;Integrated Security=True;";
2. 用ExecuteNonQuery执行非查询语句
RESTORE和ALTER DATABASE都是不返回数据集的操作,原代码里的SqlDataReader dr = cmd.ExecuteReader();完全没必要,还可能引发额外错误,换成ExecuteNonQuery()才是正确的选择:
cmd.ExecuteNonQuery();
3. 恢复完成后恢复多用户模式
执行SET SINGLE_USER会把数据库改成单用户状态,恢复完成后记得改回多用户,避免其他用户无法访问目标数据库:
a += "ALTER DATABASE " + databesing + " SET MULTI_USER;";
修改后的完整代码
private void connTes() { try { // 修正连接字符串,连接master,且身份验证二选一 conString = "server=.\\SQLEXPRESS;database=master;user=admin;password=123;"; connnn = new SqlConnection(conString); connnn.Open(); } catch { } } private void button1_Click(object sender, EventArgs e) { connTes(); try { if (txtlocation.Text == "") { MessageBox.Show("select database"); return; } else { string databesing = "db_datatestproject"; // 直接指定目标库名,或从配置读取 string a = "ALTER DATABASE " + databesing + " SET SINGLE_USER WITH ROLLBACK IMMEDIATE;"; a += "RESTORE DATABASE " + databesing + " FROM DISK ='" + txtlocation.Text + "' WITH REPLACE;"; a += "ALTER DATABASE " + databesing + " SET MULTI_USER;"; // 恢复多用户状态 SqlCommand cmd = new SqlCommand(a, connnn); cmd.ExecuteNonQuery(); // 替换为非查询执行方法 connnn.Close(); connnn.Dispose(); MessageBox.Show("done restored"); } } catch(SqlException ex) { MessageBox.Show(ex.ToString()); } }
额外安全建议
拼接SQL语句存在SQL注入风险,如果txtlocation.Text是用户可输入的内容,建议改用参数化查询替代字符串拼接:
string a = "ALTER DATABASE @dbName SET SINGLE_USER WITH ROLLBACK IMMEDIATE;"; a += "RESTORE DATABASE @dbName FROM DISK =@backupPath WITH REPLACE;"; a += "ALTER DATABASE @dbName SET MULTI_USER;"; SqlCommand cmd = new SqlCommand(a, connnn); cmd.Parameters.AddWithValue("@dbName", databesing); cmd.Parameters.AddWithValue("@backupPath", txtlocation.Text); cmd.ExecuteNonQuery();
内容的提问来源于stack exchange,提问作者Sai
相关产品推荐
相关产品推荐

