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.Dispose(),也會一併呼叫Close()