C# 是否需要手动关闭和处理 SqlDataReader?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/744051/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 23:29:03  来源:igfitidea点击:

Is it necessary to manually close and dispose of SqlDataReader?

c#sql.netado.net

提问by Jon Ownbey

I'm working with legacy code here and there are many instances of SqlDataReaderthat are never closed or disposed. The connection is closed but, I am not sure if it is necessary to manage the reader manually.

我在这里处理遗留代码,并且有许多实例SqlDataReader从未关闭或处理过。连接已关闭,但我不确定是否需要手动管理阅读器。

Could this cause a slowdown in performance?

这会导致性能下降吗?

采纳答案by Codebrain

Try to avoid using readers like this:

尽量避免使用这样的阅读器:

SqlConnection connection = new SqlConnection("connection string");
SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection);
SqlDataReader reader = cmd.ExecuteReader();
connection.Open();
if (reader != null)
{
      while (reader.Read())
      {
              //do something
      }
}
reader.Close(); // <- too easy to forget
reader.Dispose(); // <- too easy to forget
connection.Close(); // <- too easy to forget

Instead, wrap them in using statements:

相反,将它们包装在 using 语句中:

using(SqlConnection connection = new SqlConnection("connection string"))
{

    connection.Open();

    using(SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection))
    {
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            if (reader != null)
            {
                while (reader.Read())
                {
                    //do something
                }
            }
        } // reader closed and disposed up here

    } // command disposed here

} //connection closed and disposed here

The using statement will ensure correct disposal of the object and freeing of resources.

using 语句将确保正确处理对象和释放资源。

If you forget then you are leaving the cleaning up to the garbage collector, which could take a while.

如果您忘记了,那么您会将清理工作留给垃圾收集器,这可能需要一段时间。

回答by Kon

To be safe, wrap every SqlDataReader object in a using statement.

为安全起见,将每个 SqlDataReader 对象包装在using 语句中

回答by J.W.

Just wrap your SQLDataReader with "using" statement. That should take care of most of your issues.

只需用“使用”语句包装您的 SQLDataReader。这应该可以解决您的大部分问题。

回答by Joe

Note that disposing a SqlDataReader instantiated using SqlCommand.ExecuteReader() will notclose/dispose the underlying connection.

请注意,处理使用 SqlCommand.ExecuteReader() 实例化的 SqlDataReader不会关闭/处理底层连接。

There are two common patterns. In the first, the reader is opened and closed within the scope of the connection:

有两种常见的模式。首先,读取器在连接范围内打开和关闭:

using(SqlConnection connection = ...)
{
    connection.Open();
    ...
    using(SqlCommand command = ...)
    {
        using(SqlDataReader reader = command.ExecuteReader())
        {
            ... do your stuff ...
        } // reader is closed/disposed here
    } // command is closed/disposed here
} // connection is closed/disposed here

Sometimes it's convenient to have a data access method open a connection and return a reader. In this case it's important that the returned reader is opened using CommandBehavior.CloseConnection, so that closing/disposing the reader will close the underlying connection. The pattern looks something like this:

有时让数据访问方法打开连接并返回读取器很方便。在这种情况下,重要的是使用 CommandBehavior.CloseConnection 打开返回的读取器,以便关闭/处理读取器将关闭底层连接。该模式看起来像这样:

public SqlDataReader ExecuteReader(string commandText)
{
    SqlConnection connection = new SqlConnection(...);
    try
    {
        connection.Open();
        using(SqlCommand command = new SqlCommand(commandText, connection))
        {
            return command.ExecuteReader(CommandBehavior.CloseConnection);
        }
    }
    catch
    {
        // Close connection before rethrowing
        connection.Close();
        throw;
    }
}

and the calling code just needs to dispose the reader thus:

并且调用代码只需要这样处理读取器:

using(SqlDataReader reader = ExecuteReader(...))
{
    ... do your stuff ...
} // reader and connection are closed here.