DataReader的Close時機

DataReader的Close時機

今天一早收到老大通知,說DB裡面有幾個Cursor沒有消失,那幾個都卡很久了,還好那幾個Script很好認,就去看了一下那一段的程式內容.

 


OracleConnection conn=null;
OracleCommand cmd=null;
OracleDataReader odr=null;
try
{
    conn=new OracleConnection(XXXX);
    cmd=conn.CreateCommand();
    conn.Open();
    cmd.CommandText="select * from a";
    odr=cmd.ExecuteReader();
    while (odr.Read())
    {
        .....
    }

    cmd.CommandText="select * from b";
    odr=cmd.ExecuteReader();
    while (odr.Read())
    {
        .....
    }
}
catch (Exception ex)
{
    throw ex;
}
finally
{
    if (odr!=null)
    {
        odr.Close();
        odr.Dispose();
    }
    if (cmd!=null)
    {
        cmd.Dispose();
    }
    if (conn!=null)
    {
        conn.Close();
        conn.Dispose();
    }
}

 

一開始看到finally這段,就覺得,這是不管程式如何,都一定會跑到的一段,每個都有去Close跟Dispose了,但它怎麼還會留下"證據"在DB裡?

 

這時就要看一下MSDN裡的說明 :

關閉 DataReader

用完 DataReader 物件後,請務必呼叫 Close 方法

如果您的 Command 包含輸出參數或傳回值,則必須等到 DataReader 關閉後才能使用它們。

請注意,DataReader 開啟期間,Connection 只能供該 DataReader 使用。必須等到原始 DataReader 關閉後,才能執行 Connection 的任何命令,包括建立其他 DataReader

 

看了這段說明,馬上一切真象大白,上面那段Code所犯的就是這個的錯,我在取得第一個DataReader後,並未將它給Close,而又呼叫了另一個DataReader,雖然在Finally有呼叫到DataReader.Close,但還是晚了一步.

 

所以上述的Code,必需在while (odr.Read())迴圈跑完後,因為不再使用,就要馬上Close [下述Code的第16,25行],後續就可以再繼續使用.


OracleConnection conn=null;
OracleCommand cmd=null;
OracleDataReader odr=null;
try
{
    conn=new OracleConnection(XXXX);
    cmd=conn.CreateCommand();
    conn.Open();
    cmd.CommandText="select * from a";
    odr=cmd.ExecuteReader();
    while (odr.Read())
    {
        .....
    }

    odr.Close();

    cmd.CommandText="select * from b";
    odr=cmd.ExecuteReader();
    while (odr.Read())
    {
        .....
    }

    odr.Close();

}
catch (Exception ex)
{
    throw ex;
}
finally
{
    if (odr!=null)
    {
        odr.Close();
        odr.Dispose();
    }
    if (cmd!=null)
    {
        cmd.Dispose();
    }
    if (conn!=null)
    {
        conn.Close();
        conn.Dispose();
    }
}


參考來源 :

使用 DataReader 擷取資料

*DataReader.Dispose(),也會一併呼叫Close()

DbDataReader.Dispose 方法