我正在制作一个与某些SQL Server数据库交互的C#程序。问题是如果我连接到数据库(dbA)然后关闭此连接并打开另一个连接到另一个数据库(dbB)然后执行还原dbA,则SqlException会触发说该数据库(dbA)正在使用中。但是,如果我执行程序并仅连接到dbB,我可以毫无问题地恢复其他数据库,就像第一个连接被保存一样。无论如何这里是连接应该打开和关闭的代码:
private bool CheckConnection()
{
bool res = false;
string conString = string.Empty;
if (!String.IsNullOrEmpty(serverBox.Text) && !String.IsNullOrEmpty(dbBox.Text))
{
conString = ConcatConString(dbBox.Text);
using (SqlConnection conn = new SqlConnection(conString))
{
conn.Open();
if (conn.State == ConnectionState.Open)
{
res = true;
}
}
}
return res;
}
答案 0 :(得分:3)
ADO.NET使用连接池来重用昂贵的连接对象。当您关闭连接时,将回滚任何现有事务,重置其服务器端状态,并将其置于连接池中,以便为下一个Open
命令进行操作。
但是,当您尝试采取诸如关闭服务器,恢复数据库等的激烈操作时,仍然将服务器连接视为服务器连接。这意味着您必须采取明确的操作并告诉服务器它没关系继续。
在这种情况下,您需要将数据库设置为SINGLE USER模式,执行还原操作,然后将其恢复为MULTI USER模式,例如:
ALTER DATABASE [MyDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
RESTORE DATABASE [MyDB] ...
ALTER DATABASE [MyDB] SET MULTI_USER
当您在恢复时选中“关闭现有数据库连接”选项时,这就是SSMS所做的事情
如果您想给现有连接留一些时间,也可以使用WITH ROLLBACK AFTER xx SECONDS
。但在这种情况下,您将覆盖数据库。
答案 1 :(得分:0)
关闭连接不会在数据库中关闭它,它只返回与ADO.Net维护的池的连接。通常我永远不会建议这样做,但似乎你可能有一个合法的情况来禁用连接池。
在连接字符串中,将Pooling
属性设置为no
或false
,并且连接应该在服务器上实际关闭。
您可以通过在以下代码中启用或禁用连接池的SSMS中运行sp_who2
来观察其工作原理:
class Program
{
static void Main(string[] args)
{
SqlConnectionStringBuilder bldr = new SqlConnectionStringBuilder();
bldr.IntegratedSecurity = true;
bldr.InitialCatalog = "YourDB";
bldr.DataSource = "(localdb)\\YourServer";
bldr.Pooling = false; //Comment and uncomment this and run sp_who2
using (SqlConnection con = new SqlConnection(bldr.ConnectionString))
{
con.Open();
}
}
}
除非你的程序是唯一连接的程序,否则不要这样做。我得到的印象是该程序专门用于恢复数据库。如果你在数据库上有其他客户端,那么这将会影响性能。更新