SqlConnection SqlCommand SqlDataReader IDisposable

SqlConnectionSqlCommandSqlDataReader都实现了IDisposable接口。 我阅读了最佳做法,始终将IDisposables换成using块。

所以,查询数据的常见情况看起来像这样(当然,在更大的背景下,像linq2sql这样的映射工具将是合适的,但是假设我们想在这里使用这种方法):

 using (SqlConnection cn = new SqlConnection("myConnectionstring")) { using (SqlCommand cm = new SqlCommand("myQuery", cn)) { // maybe add sql parameters using (SqlDataReader reader = cm.ExecuteReader()) { // read values from reader object return myReadValues; } } } 

这是正确的方式还是可以被认为是矫枉过正? 我对using块的这种嵌套级别有些不确定,但是当然我想要正确的做法。 谢谢!

这是100%正确的方法。 如果一个类利用了IDisposable它应该被封装在一个using语句中,以确保调用Dispose()方法。 此外,不应该轻易地与在那种类似SQL Server上pipe理的外部技术进行通信。 SqlCommand对象实现IDisposable有一个很好的理由。 下面的代码是SqlCommand对象的Dispose()方法:

 protected override void Dispose(bool disposing) { if (disposing) { this._cachedMetaData = null; } base.Dispose(disposing); } 

正如你所看到的,它释放了对_cachedMetaData对象的引用,所以它也可以被清理。

你可以使用下面的排版方式让代码更靠近左边:

 using (SqlConnection cn = new SqlConnection("myConnectionstring")) using (SqlCommand cm = new SqlCommand("myQuery", cn)) using (SqlDataReader reader = cm.ExecuteReader()) { // read values from reader object return myReadValues; } 

正如其他人已经指出的那样,使用三个嵌套的using块是正确的。

这是正确的方法,如果你将与读者完成。 有时,你需要读者保持开放(也许你的方法返回它),所以它立即丢弃读者是行不通的。 在这些情况下,ExecuteReader的重载可以帮助您:

 var cn = new SqlConnection("myConnectionstring"); var cm = new SqlCommand("myQuery", cn); var reader = cm.ExecuteReader(CommandBehavior.CloseConnection); return reader; 

这将保持连接和读者打开。 一旦读取器被closures/处置,它也将closures(并处置)连接。

 using(var reader = GetReader()) //which includes the code above { ... } // reader is disposed, and so is the connection. 

是的,这是正确的。 你可以错过嵌套使用的大括号,因为它们是一个声明,但我不认为这增加了可读性。

这并不过分。 using块是一个很好的做法,因为它确保即使抛出exception,也会调用对象的Dispose()方法。

尽pipe如此,还是有这个名字的。 这就是所谓的代码糖 。 所以:

 using (foo bar = new foo()) { //...snip } 

简短的代码是:

 foo bar = null; Exception error = null; try { bar = new foo(); // ...snip } catch (Exception ex) { error = ex; } finally { if (bar != null) bar.Dispose(); if (error != null) throw error; } 

任何一种forms都与另一种forms相同,它们只是写不同的方式来写同一件事情。 换句话说, forwhile之间for区别是相同的:它们基本上是相同的,但是以不同的方式使用。

using是首选,因为它使代码更短,更可读,并自动为您处置。 至于你是否应该使用它,不要听那些说你总是应该做点什么的人。 这是一个很好的习惯,但是知道什么时候使用为什么要使用以及使用或不使用某些东西的好处和后果做某事更值得, 因为人们说你应该这样做

编辑: Eren的答案有一个例子,你不希望reader有一个using块。

我没有看到处置SqlCommand任何意义。 SqlConnectionSqlDataReader应该被丢弃。

SqlConnection因为当它超出范围时它不会自行closures。

SqlDataReader可以保持SqlConnection繁忙,直到阅读器closures。

甚至没有MSDN的例子处置的SqlCommand

我不是专家,但我知道使用被翻译成try / finally块,也许你可以包装SqlConnection,SqlCommand和SqlDataReader到一个独特的尝试/最后

 try { // code here with SqlConnection, SqlCommand and SqlDataReader } finally { // Dispose call on SqlConnection, SqlCommand and SqlDataReader }