【原文地址:http://www.cnblogs.com/agian/articles/1648835.html】html
其用在ExecuteReader(c)中,返回对象前不能关闭数据库链接,须用CommandBehavior.CloseConnection;面试
这是一个关于实际知识点的问题,面试官考查的是应聘者数据库访问的编程经验。本节将针对这个问题展开具体的分析。对于此类关于具体知识点的问题,读者在平时应该注意积累,这样在面试中才能从容应答。数据库
所涉及的知识点编程
CommandBehavior.CloseConnection的使用测试
分析问题htm
因为流模式读取数据库的特色,在具体应用时很难肯定数据库链接什么时候才能被关闭,由于读取的动做是连续进行的,下面是一个常见的数据访问层的静态方法:
/// <summary>对象
/// 常见的获取SqlDataReader方法blog
/// 一般的数据访问层都会提供这个方法字符串
/// </summary>get
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();那返回后该链接
将永远没法关闭,由于调用方没法
//获得链接对象
}
}
正如代码注释里描述的那样,这样的方法既不能关闭链接,也不能保持链接打开状态。不少系统为了解决这样两难的境地,只能放弃使用Reader模式的数据源,或者把链接对象交给方法调用者,以便进行关闭。
而CommandBehavior.CloseConnection的功能刚好就是为了不相似的尴尬境地,它可以保证当SqlDataReader对象被关闭时,其依赖的链接也会被自动关闭。代码9-2展现了使用CommandBehavior.CloseConnection和不使用CommandBehavior.CloseConnection的区别。
这里以SqlDataReader为例进行说明,对于其余命名空间下的XXXDataReader对象,其功能是相似的。
首先为了展现功能,代码9-2包含了两个静态的返回SqlDataReader的方法,其中一个在执行ExecuteReader方法时传入了CommandBehavior.CloseConnection方法。
代码9-2 使用CommandBehavior.CloseConnection:UseCommandBehavior.cs
partial class UseCommandBehavior
{
//数据库看链接字符串
const String conn_String =
"Server=localhost;Integrated Security=true;database=NetTest";
const String Sql = "select * from dbo.DepartCost";
/// <summary>
/// 使用CommandBehavior.CloseConnection
/// </summary>
/// <param name="con">为了测试须要,传入链接对象</param>
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
{
//由于使用了CommandBehavior.CloseConnection,
//这里不须要关闭链接
//con.Close();
}
}
/// <summary>
/// 不使用CommandBehavior.CloseConnection
/// </summary>
/// <param name="con">为了测试须要,传入链接对象</param>
static SqlDataReader GetReader_NoCloseConnection(SqlConnection con)
{
try
{
//打开链接,执行查询
//而且返回SqlDataReader
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = Sql;
SqlDataReader dr = cmd.ExecuteReader();
return dr;
}
finally
{
//为了使返回的SqlDataReader可用,这里不能关闭链接
//con.Close();
}
}
}
能够看到,不管是否使用CommandBehavior.CloseConnection,两个方法都没有在最终关闭链接,可是它们不关闭链接的缘由并不相同。准备好了两个方法以后,就从主方法中分别调用这两个方法来进行测试,以查看从使用了CommandBehavior.CloseConnection的方法中返回的SqlDataReader对象是否在关闭的同时自动关闭链接,如代码9-3所示。
代码9-3 使用CommandBehavior.CloseConnection:UseCommandBehavior.cs
partial class UseCommandBehavior
{
/// <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();
}
}
}
下面是代码的执行结果:
测试使用了CommandBehavior.CloseConnection的方法:
读取完毕后的链接状态:Closed
测试没有使用CommandBehavior.CloseConnection的方法:
读取完毕后的链接状态:Open
正如读者所看到的,使用了CommandBehavior.CloseConnection获得的SqlDataReader对象,在关闭的同时会自动地关闭其依赖的数据库链接对象,这个特性解决了数据访问层编写中的困境。
答案
CommandBehavior.CloseConnection解决了流读取数据模式下,数据库链接不能有效关闭的状况。当某个XXXDataReader对象在生成时使用了CommandBehavior.CloseConnection,那数据库链接将在XXXDataReader对象关闭时自动关闭。