简体   繁体   English

SqlConnection SqlCommand SqlDataReader IDisposable

[英]SqlConnection SqlCommand SqlDataReader IDisposable

SqlConnection , SqlCommand and SqlDataReader all implement the IDisposable interface. SqlConnectionSqlCommandSqlDataReader都实现了IDisposable接口。 I read about a best practice to always wrap IDisposables into a using block. 我读到了一个总是将IDisposables包装成一个using块的最佳实践。

So, my common scenario for querying data would look something like this (in greater context of course a mapping tool like linq2sql would be suitable, but lets just assume we want to use this approach here): 因此,我查询数据的常见场景看起来就像这样(在更大的上下文中,像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;
        }
    }
}

Is this the correct way or could that be considered overkill? 这是正确的方式还是被认为是矫枉过正? I am a little unsure about this level of nesting using blocks, but of course i want to do it the correct way. 我对using块的嵌套级别有点不确定,但当然我想以正确的方式做到这一点。 Thanks! 谢谢!

This is 100% the correct way. 这是100%正确的方法。 If a class leverages IDisposable it should be wrapped in a using statement to ensure that the Dispose() method is called. 如果类利用IDisposable ,则应将其包装在using语句中以确保调用Dispose()方法。 Further, communicating with an outside technology -unmanaged at that -like SQL Server shouldn't be taken lightly. 此外,不应轻率地与外部技术进行通信 - 不管那样的SQL Server。 The SqlCommand object implements IDisposable for a very good reason. SqlCommand对象实现IDisposable是一个很好的理由。 The code below is the Dispose() method for the SqlCommand object: 下面的代码是SqlCommand对象的Dispose()方法:

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

and as you can see, it's releasing a reference to the _cachedMetaData object so that it too can get cleaned up. 正如您所看到的,它正在释放对_cachedMetaData对象的引用,以便它也可以被清除。

You can use the following way of typography to get the code closer to the left: 您可以使用以下排版方式使代码更靠近左侧:

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;
}

As other already pointed out, using three nested using blocks is correct though. 正如其他已经指出的那样,使用三个嵌套的using块是正确的。

That is the correct way, if you will be done with the reader. 这是正确的方法,如果你将与读者完成。 Sometimes, you need the reader to remain open (maybe your method returns it), so it disposing the reader right away would not work. 有时候,你需要读者保持开放状态(也许你的方法会返回它),所以立即处理读者是行不通的。 In those cases, there is an overload of the ExecuteReader that can help you: 在这些情况下,ExecuteReader会超载,可以帮助您:

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

This will keep the connection and the reader open. 这将保持连接和阅读器打开。 Once the reader is closed/disposed, it will also close (and dispose) the connection as well. 一旦阅读器关闭/丢弃,它也将关闭(并处置)连接。

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

Yep that's correct. 是的,这是正确的。 You can miss the braces out in nested using as they are one statement, but I don't feel that adds to readability. 你可以错过嵌套使用的大括号,因为它们是一个语句,但我觉得这不会增加可读性。

This is not overkill. 这不是矫枉过正。 A using block is good practice because it ensures that the Dispose() method of the object will be called, even if an exception is thrown. using块是一种很好的做法,因为它确保即使抛出异常也会调用对象的Dispose()方法。

There is a name for this kind of thing, though. 但是,这种事情有一个名字。 It's called code sugar . 它被称为代码糖 So: 所以:

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

Is short hand code for: 是简写代码:

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;
}

Either form is equal to the other, they're just different ways to write the same thing. 任何一种形式都等于另一种形式,它们只是用不同的方式来写同一种东西。 In other words, same difference between for and while : they do basically the same thing but are used in different ways. 换句话说, forwhile之间for区别相同:它们基本上是相同的,但以不同的方式使用。

using is preferred because it makes the code shorter and more readable, and automates the disposal for you. using是首选,因为它使代码更短,更易读,并自动处理。 As to whether you should use it, though, don't listen to people who say you should always do something. 至于你是否应该使用它,不要听那些说你应该总是做某事的人。 It's good practice, granted, but knowing when to use , why to use and the benefits and consequences of using, or not using something is worth way more than doing something because people say you should . 这是好的做法,被授予,但知道何时使用为什么使用以及使用或不使用某些东西的好处和后果做某事更有价值, 因为人们说你应该这样做

Edit: Eren's answer has an example of a case where you wouldn't want to have a using block for the reader . 编辑: Eren的答案有一个例子,你不希望有一个readerusing块。

I don't see any point in disposing the SqlCommand . 我没有看到处理SqlCommand任何意义。 The SqlConnection and SqlDataReader should be disposed of though. 但是应该处理SqlConnectionSqlDataReader

The SqlConnection because it won't close by itself when it goes out of scope. SqlConnection因为它超出范围时不会自行关闭。

The SqlDataReader can keep the SqlConnection busy until the reader is closed. SqlDataReader可以保持SqlConnection忙,直到读取器关闭。

Not even MSDN examples dispose of the SqlCommand . 甚至MSDN示例都没有处理SqlCommand

I'm not an expert but i know that the using is translated into a try/finally block maybe you can wrap the SqlConnection, SqlCommand and SqlDataReader into a unique try/finally 我不是专家,但我知道将使用转换为try / finally块,也许你可以将SqlConnection,SqlCommand和SqlDataReader包装成一个独特的try / finally

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM