这两天在对照几个典型的.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