Welcome 微信登录

首页 / 网页编程 / ASP.NET / Trick: 巧用.NET Reflection从SqlConnection回溯到打开着的SqlDataReader

Trick: 巧用.NET Reflection从SqlConnection回溯到打开着的SqlDataReader2011-08-01 博客园 Jialiang相信使用过ADO.NET的同志多半都见过这个exception吧:

There is already an open DataReader associated with this Command which must be closed first.

抛出这个exception的主要原因是:一个SqlConnection只能和一个开着的SqlDataReader相关联。当开 发人员忘记关掉打开的SqlDataReader,而又尝试打开一个新的SqlDataReader的时候,BCL就会抛出上述 异常。重现方法如下:

SqlConnection conn = new SqlConnection(connStr);
conn.Open();

SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Person";
SqlDataReader reader1 = cmd.ExecuteReader();
while (reader1.Read())
{ /* Read Fields */ }

// Forget to close the DataReader

cmd.CommandText = "SELECT * FROM Course";
SqlDataReader reader2 = cmd.ExecuteReader(); // Throws the above exception
while (reader2.Read())
{ /* Read Fields */ }

这段代码很简单,我们一眼就能看出那个罪恶的DataReader。但是在实际的开发环境中,代码的封装 会造成当 SqlDataReader reader2 = cmd.ExecuteReader(); 抛出exception时,我们很难找到那个忘关 的DataReader。

下面,我将介绍一种方法,从SqlConnection回溯到打开着的SqlDataReader。

SqlConnection自身是没有任何public的方法可以返回当前打开着的SqlDataReader的,但是 SqlConnection却有一些internal method能帮助我们得到所要的信息。它们是:

SqlConnectionSqlInternalConnection GetOpenConnection();
SqlInternalConnectionSqlDataReader FindLiveReader(SqlCommand command);
SqlDataReaderSqlCommand Command { get; }