i Dispose一个SqlConnection对象,但当然是it isn't really closed。我需要关闭连接以不保持数据库对象的锁定。如何防止闭合连接锁定?
对于那些不知道的人说明上述信息:
关闭ADO或ADO.NET连接时,实际上并未切断与SQL Server的连接。 ADO / ADO.NET基础结构可以保持连接,以防您再次使用它。这些连接在所谓的“连接池”中保持不变。
几分钟未使用后,连接将实际关闭。虽然,不是真的。 TCP / IP有自己的方法来保持TCP连接打开几分钟(在“ CLOSE_WAIT ”状态)。如果您要求打开到同一IP:端口的TCP连接,则会执行此操作。如果是这样,它可以使用已经打开的TCP连接。
使用连接池和SQL Server,仍然建立与SQL Server的连接。每个连接都有一个它所在的数据库上下文。只要连接位于该数据库中:它就拥有该数据库上的共享数据库(S-DB)锁。
共享数据库锁只是意味着“请不要删除此数据库。”
如何防止它在我的数据库上持有共享锁,同时保持连接池的好处?
我的ad-hoc解决方案现在每次都是开发人员调用Dispose:
connection.Dispose()
将其更改为对全局辅助函数的调用:
Database.DisposeConnection(connection);
将数据库上下文更改为 master :
public static void DisposeConnection(SqlConnection connection)
{
//Stop holding a database lock - in my database at least
ADOHelper.ExecuteNonQuery(connection, "USE master");
connection.Dispose();
}
它解决了我眼前的问题;已关闭的连接未锁定我的数据库。
但是现在我担心连接池会让它的大脑混乱 - 因为我在后面切换了数据库上下文。
如果有人不知道,或者不这么认为:
来自the SDK:
关闭和处理功能正常 等效。
答案 0 :(得分:7)
您可以将数据库置于单用户模式下以进行还原。 IIRC,就像这样......
ALTER DATABASE TheDatabaseToRestore SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE TheDatabaseToRestore
FROM DISK =N'Z:\Path\To\Backup\BackupFile';
ALTER DATABASE TheDatabaseToRestore SET MULTI_USER;
请参阅:Obtain Exclusive Access to Restore SQL Server和/或Restore Database Backup using SQL了解更多背景信息。
编辑:单用户模式用于备份和恢复(在非快速版本上,我经常使用它)。使用它会启动所有其他连接,并且无法建立新连接。我没有使用各种“WITH”选项,例如“ROLLBACK IMMEDIATE”,但它们的用法似乎很简单。
答案 1 :(得分:3)
你试过SqlClient.ClearPool吗?
来自MSDN:
ClearPool清除连接池 与...有关 连接。如果有其他连接 与连接相关联正在使用中 在通话时,他们是 适当标记并被丢弃 (而不是返回到 pool)当他们调用Close时。
只需在每个连接上调用ClearPool,但如果执行此操作,则会失去池效益。
public class DataFactory
{
public SqlConnection CreateConnection(string connString)
{
SqlConnection conn = new SqlConnection(connString);
SqlClient.ClearPool(conn);
return conn;
}
}
或者,您可以使用连接字符串的Pooling属性禁用所有池:
string connString = "Data Source=MYSERVER;Initial Catalog=myDb;Integrated Security=true;Pooling=false"
答案 2 :(得分:1)
正如您所说,当您关闭或处置连接时,它会返回到池中,但并未真正关闭。
然后您需要做什么来关闭池中的所有连接。这可以使用ClearAllPools命令完成。
ClearAllPools重置(或清空)连接池。如果有 在使用时使用的连接 打电话,他们被适当标记 并将被丢弃(而不是 关闭时返回池中 在他们身上被召唤。
还有一个ClearPool命令可以执行相同的操作,但只需一个连接。
希望这有帮助
西拉
答案 3 :(得分:1)
执行“USE TempDB;”第一。然后关闭它。
或“USE master;”,如果这更符合您的喜好。
在正常生产操作期间,这些数据库中的任何一个数据库上的S-DB锁都无关紧要,因为您无法摆脱任何一个数据库并继续运行服务器。
答案 4 :(得分:0)
阅读评论,您想恢复它。
好的,让它脱机。
还原不是应用程序应该做的事情,因此DBA在RESTORE之前运行它。
ALTER DATABASE foo SET OFFLINE WITH ROLLBACK IMMEDIATE