簡體   English   中英

將圍繞DataReader放置一個“using”語句關閉嗎?

[英]Will putting a “using” statement around a DataReader close it?

我經常寫這樣的DataReader代碼:

try
{
    dr = cmd.ExecuteReader(CommandBehavior.SingleResult);
    while (dr.Read())
    {
        // Do stuff
    }
}
finally
{
    if (dr != null) { dr.Close(); }
}

更換try是否安全, finally只需using DataReader創建的using塊? 我想知道的原因是因為在我看到的所有Microsoft示例中,他們都使用了一個用於連接,但總是在DataReader上顯式調用Close()

Heres是使用DataReader檢索數據的一個例子(ADO.NET)

static void HasRows(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new SqlCommand(
          "SELECT CategoryID, CategoryName FROM Categories;",
          connection);
        connection.Open();

        SqlDataReader reader = command.ExecuteReader();

        if (reader.HasRows)
        {
            while (reader.Read())
            {
                Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
                    reader.GetString(1));
            }
        }
        else
        {
            Console.WriteLine("No rows found.");
        }
        reader.Close();
    }
}

是。 using調用Dispose。 在SqlDataReader上調用Dispose會關閉它。

這是從Reflector收集的SqlDataReader的偽代碼:

    public void Dispose()
    {
        this.Close();
    }

    public override void Close()
    {
        if( !IsClosed )
            CloseInternal(true);
    }

    private void CloseInternal(bool closeReader)
    {
        try
        {
            // Do some stuff to close the reader itself
        }
        catch(Exception ex)
        {
            this.Connection.Abort();
            throw;
        }

        if( this.Connection != null && CommandBehavior.CloseConnection == true )
        {
            this.Connection.Close();
        }
    }

通常, using()調用Dispose()並依次調用close()

對於DataReader,只有在設置了CommandBehavior.CloseConnection時才會調用Close(請參閱本文的評論http://weblogs.asp.net/joseguay/archive/2008/07/22/ensure-proper-closure-amp -disareal-of-a-datareader.aspx )。

編輯: 這篇文章說了一些有趣的東西:

SqlDataReader上的Close()方法調用InternalClose()方法,該方法不調用Dispose。 請注意,之前我們說過這樣做的正確方法是讓您的近距離呼叫處理。 為了使它更令人困惑,Dispose()方法實際上調用了Close()方法,因此對於此對象,順序是相反的。

根據我的記憶,如果在使用塊中發生異常,則仍然會在對象上調用Dispose方法。 我通常對所有一次性對象都有一個Using語句,沒有Try..Catch。

編輯:忘了說對於某些對象,調用Dispose將依次為該對象調用Close。

此處的示例不同,我的做法是使用一個使用塊來連接,命令和閱讀器。 請注意,您可以使用塊堆疊嵌套以降低縮進成本。

static void HasRows(SqlConnection connection)
{
    using (connection)
    using (SqlCommand command = new SqlCommand(
    "SELECT CategoryID, CategoryName FROM Categories;",
    connection))
    {
        connection.Open();
        using (SqlDataReader reader = command.ExecuteReader())
        {
            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
                        reader.GetString(1));
                }
            }
            else
            {
                Console.WriteLine("No rows found.");
            }
            reader.Close();
        }   
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM