2011年5月22日 这两天在对照几个典型的.net网站的时候,发现了一个小小的问题,大家在对数据库操作的时候经常会用到
SqlDataReader,这个方法在调用完之后是要及时关闭的,问题就是什么时候关闭是合适的?
为了这个问题我专门上微软的官方论坛找了点东西,我在这里和我平时用的稍微的对比了一下
我们平时用方法一般是(至少我以前看到的是的,特别是很多.net书籍上):
///
<summary>
/// 常见的获取SqlDataReader方法
/// 通常的数据访问层都会提供这个方法
/// </summary>
static SqlDataReader GetReader()
{
// 通过连接字符串获取连接
SqlConnection con = new SqlConnection(conn_String);
try
{
// 打开连接,执行查询
// 并且返回SqlDataReader
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = Sql;
SqlDataReader dr = cmd.ExecuteReader();
return dr;
}
finally
{
// 这里的代码就是问题所在
// 如果这里执行关闭:
con.Close();
// 那返回的SqlDataReader将毫无用处,因为其
// 依赖的连接已经关闭
// 如果这里不执行con.Close();那返回后该连接将永远无法关闭,因为调用方无法
// 得到连接对象
}
}
/// 常见的获取SqlDataReader方法
/// 通常的数据访问层都会提供这个方法
/// </summary>
static SqlDataReader GetReader()
{
// 通过连接字符串获取连接
SqlConnection con = new SqlConnection(conn_String);
try
{
// 打开连接,执行查询
// 并且返回SqlDataReader
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = Sql;
SqlDataReader dr = cmd.ExecuteReader();
return dr;
}
finally
{
// 这里的代码就是问题所在
// 如果这里执行关闭:
con.Close();
// 那返回的SqlDataReader将毫无用处,因为其
// 依赖的连接已经关闭
// 如果这里不执行con.Close();那返回后该连接将永远无法关闭,因为调用方无法
// 得到连接对象
}
}
我在微软的官方实例petshop中看的方法却是:
static
SqlDataReader GetReader_CloseConnection(SqlConnection con)
{
try
{
// 打开连接,执行查询
// 并且返回SqlDataReader
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = Sql;
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dr;
}
finally
{
// 不需要使用con.Close();
}
}
{
try
{
// 打开连接,执行查询
// 并且返回SqlDataReader
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = Sql;
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dr;
}
finally
{
// 不需要使用con.Close();
}
}
我找了找CommandBehavior.CloseConnection的作用
CommandBehavior.CloseConnection的功能恰好就是为了避免类似的尴尬境地,它能够保证当SqlDataReader对象被关闭时,其依赖的连接也会被自动关闭。
只需要在使用DataReader对象之后的时候,将DataReader对象关闭即可,这样conn就自己关闭了。找了个小例子:
///
<summary>
/// 测试方法
/// </summary>
static void Main( string [] args)
{
// 建立连接
SqlConnection con = new SqlConnection(conn_String);
try
{
// 测试使用了CommandBehavior.CloseConnection的方法
Console.WriteLine( " 测试使用了CommandBehavior.CloseConnection的方法: " );
SqlDataReader sdr = GetReader_CloseConnection(con);
while (sdr.Read()) { }
sdr.Close();
Console.WriteLine( " 读取完毕后的连接状态: " + con.State.ToString());
// 测试没有使用CommandBehavior.CloseConnection的方法
Console.WriteLine( " 测试没有使用CommandBehavior.CloseConnection的方法: " );
SqlDataReader sdr1 = GetReader_NoCloseConnection(con);
while (sdr1.Read()) { }
sdr1.Close();
Console.WriteLine( " 读取完毕后的连接状态: " +
con.State.ToString());
Console.Read();
}
finally
{
// 确保连接被关闭
if (con.State != ConnectionState.Closed)
con.Close();
}
}
/// 测试方法
/// </summary>
static void Main( string [] args)
{
// 建立连接
SqlConnection con = new SqlConnection(conn_String);
try
{
// 测试使用了CommandBehavior.CloseConnection的方法
Console.WriteLine( " 测试使用了CommandBehavior.CloseConnection的方法: " );
SqlDataReader sdr = GetReader_CloseConnection(con);
while (sdr.Read()) { }
sdr.Close();
Console.WriteLine( " 读取完毕后的连接状态: " + con.State.ToString());
// 测试没有使用CommandBehavior.CloseConnection的方法
Console.WriteLine( " 测试没有使用CommandBehavior.CloseConnection的方法: " );
SqlDataReader sdr1 = GetReader_NoCloseConnection(con);
while (sdr1.Read()) { }
sdr1.Close();
Console.WriteLine( " 读取完毕后的连接状态: " +
con.State.ToString());
Console.Read();
}
finally
{
// 确保连接被关闭
if (con.State != ConnectionState.Closed)
con.Close();
}
}
读取完毕后的连接状态:Closed
测试没有使用CommandBehavior.CloseConnection的方法:
读取完毕后的连接状态:Open
正如读者所看到的,使用了CommandBehavior.CloseConnection得到的SqlDataReader对象,在关闭的同时会自动地关闭其依赖的数据库连接对象,这个特性解决了数据访问层编写中的困境。
转自:http://hi.baidu.com/516%D0%A1%C5%DA/blog/item/30a79ede7738d51962279808.html