我是不是必须在处理 SQLConnection 之前关闭()它?
Posted
技术标签:
【中文标题】我是不是必须在处理 SQLConnection 之前关闭()它?【英文标题】:Do I have to Close() a SQLConnection before it gets disposed?我是否必须在处理 SQLConnection 之前关闭()它? 【发布时间】:2010-11-14 19:32:16 【问题描述】:根据我的其他question here about Disposable objects,我们应该在 using 块结束之前调用 Close() 吗?
using (SqlConnection connection = new SqlConnection())
using (SqlCommand command = new SqlCommand())
command.CommandText = "INSERT INTO YourMom (Amount) VALUES (1)";
command.CommandType = System.Data.CommandType.Text;
connection.Open();
command.ExecuteNonQuery();
// Is this call necessary?
connection.Close();
【问题讨论】:
【参考方案1】:使用.NET Reflector反汇编SqlConnection:
protected override void Dispose(bool disposing)
if (disposing)
this._userConnectionOptions = null;
this._poolGroup = null;
this.Close();
this.DisposeMe(disposing);
base.Dispose(disposing);
它在 Dispose() 内部调用 Close()
【讨论】:
@statenjason:您能说一下您如何利用反汇编程序线 .net 反射器吗? @odiseh 只需下载.NET Reflector,运行reflector.exe,就可以打开任何.net DLL(包括标准库)。它为您提供类似于 Visual Studio 的对象浏览器的树形结构,但是,您可以右键单击任何类或方法并单击“反汇编”,然后它将以 C# 或 VB 将源返回给您,无论您在选项。【参考方案2】:由于你有一个 using 块,将调用 SQLCommand 的 Dispose 方法并关闭连接:
// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
if (disposing)
this._userConnectionOptions = null;
this._poolGroup = null;
this.Close();
this.DisposeMe(disposing);
base.Dispose(disposing);
【讨论】:
this._poolGroup = null; 是否意味着连接没有回到连接池?所以我会有 n-1 个连接?【参考方案3】:不,无论如何,使用块都会为您调用Dispose()
,因此无需调用Close()
。
【讨论】:
对不起,我应该说,对于大多数实现 IDisposable 并具有 Close() 方法的对象,调用 Close() 最终会在后台为您调用 Dispose()。 这不是反过来吗?Dispose()
调用 Close()
,反之亦然?
通常两者兼而有之。出于某种原因,他们决定实现 Close 也会调用 Dispose。对于 SqlConnection 来说,这没什么大不了的,但是如果您关闭 StreamWriters 然后 Dispose 它们,StreamWriters 会抛出异常。我的猜测是,他们不会仅仅因为这是人们现在所期望的而改变这种行为。【参考方案4】:
using 关键字将正确关闭连接,因此不需要额外调用 Close。
来自 SQL Server Connection Pooling 上的 MSDN 文章:
“我们强烈建议您始终 关闭连接 完成使用它,以便 连接将返回到 水池。您可以使用 的 Close 或 Dispose 方法 连接对象,或打开所有 using 语句中的连接 在 C# 中"
SqlConnection.Dispose使用.NET Reflector的实际实现如下:
// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
if (disposing)
this._userConnectionOptions = null;
this._poolGroup = null;
this.Close();
this.DisposeMe(disposing);
base.Dispose(disposing);
【讨论】:
+1 用于 MSDN 链接 - 我喜欢 reflector\ILspy 和其他人一样,但我想去文档中寻找答案。【参考方案5】:使用Reflector,可以看到SqlConnection
的Dispose
方法实际上确实调用了Close()
;
protected override void Dispose(bool disposing)
if (disposing)
this._userConnectionOptions = null;
this._poolGroup = null;
this.Close();
this.DisposeMe(disposing);
base.Dispose(disposing);
【讨论】:
【参考方案6】:不,没有必要在调用 Dispose 之前关闭连接。
某些对象(如 SQLConnections)可以在调用 Close 之后重新使用,但在调用 Dispose 之后则不能。对于其他对象,调用 Close 与调用 Dispose 相同。 (ManualResetEvent 和 Streams 我认为的行为是这样的)
【讨论】:
【参考方案7】:不是,SqlConnection类继承自IDisposable,遇到使用结束(针对连接对象)时,会自动调用SqlConnection类上的Dispose。
【讨论】:
【参考方案8】:不,在 SqlConnection 上调用 Dispose() 也会调用 Close()。
MSDN - SqlConnection.Dispose()
【讨论】:
以上是关于我是不是必须在处理 SQLConnection 之前关闭()它?的主要内容,如果未能解决你的问题,请参考以下文章
using(SqlConnection connection=new SqlConnection(connectionString))
如何判断SqlConnection是否附加了SqlDataReader?
处理SqlConnection、SqlDataReader、SqlCommand 时要捕获哪些异常?
为啥不用 DbConnection 而不是 SqlConnection 或 OracleConnection?
求大侠帮忙,好多次调试都在SqlConnection conn = new SqlConnection(connStr);出现用户代码未处理