是否有必要手动关闭和处置SqlDataReader?

时间:2009-04-13 14:26:39

标签: c# sql .net ado.net

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

这会导致性能下降吗?

4 个答案:

答案 0 :(得分:114)

尽量避免使用这样的读者:

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

相反,请使用语句将它们包装起来:

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

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

如果你忘了,那么你要把清洁工作留在垃圾收集器上,这可能需要一段时间。

答案 1 :(得分:47)

请注意,使用SqlCommand.ExecuteReader()实例化处理SqlDataReader将关闭/处置基础连接。

有两种常见的模式。在第一个中,读者在连接范围内打开和关闭:

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

有时,使用数据访问方法打开连接并返回阅读器会很方便。在这种情况下,使用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;
    }
}

并且调用代码只需要处理读者:

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

答案 2 :(得分:10)

为安全起见,请将每个SqlDataReader对象包装在using statement

答案 3 :(得分:5)

使用“using”语句包装SQLDataReader。这应该照顾你的大多数问题。