1.  

其用在ExecuteReader(c)中,返回对象前不能关闭数据库连接,须用CommandBehavior.CloseConnection;

  1.  

这是一个关于实际知识点的问题,面试官考查的是应聘者数据库访问的编程经验。本节将针对这个问题展开具体的分析。对于此类关于具体知识点的问题,读者在平时应该注意积累,这样在面试中才能从容应答。

  1.  

所涉及的知识点

  1.  

CommandBehavior.CloseConnection的使用

  1.  

分析问题

  1.  

由于流模式读取数据库的特点,在具体应用时很难确定数据库连接何时才能被关闭,因为读取的动作是连续进行的,下面是一个常见的数据访问层的静态方法:

  1.  
  2. /// <summary>
  3.  
  4. /// 常见的获取SqlDataReader方法
  5.  
  6. /// 通常的数据访问层都会提供这个方法
  7.  
  8. /// </summary>
  9.  
  10. static SqlDataReader GetReader()
  11.  
  12. {
  13.  
  14. //通过连接字符串获取连接
  15.  
  16. SqlConnection con = new SqlConnection(conn_String);
  17.  
  18. try
  19.  
  20. {
  21.  
  22. //打开连接,执行查询
  23.  
  24. //并且返回SqlDataReader
  25.  
  26. con.Open();
  27.  
  28. SqlCommand cmd = con.CreateCommand();
  29.  
  30. cmd.CommandText = Sql;
  31.  
  32. SqlDataReader dr = cmd.ExecuteReader();
  33.  
  34. return dr;
  35.  
  36. }
  37.  
  38. finally
  39.  
  40. {
  41.  
  42. //这里的代码处于两难的境地
  43.  
  44. //如果这里执行关闭:con.Close();那返回的
  45.  
  46. SqlDataReader将毫无用处,因为其
  47.  
  48. //依赖的连接已经关闭
  49.  
  50. //如果这里不执行con.Close();那返回后该连接
  51.  
  52. //将永远无法关闭,因为调用方无法
  53.  
  54. //得到连接对象
  55.  
  56. }
  57.  
  58. }

正如代码注释里描述的那样,这样的方法既不能关闭连接,也不能保持连接打开状态。很多系统为了解决这样两难的境地,只能放弃使用Reader模式的数据源,或者把连接对象交给方法调用者,以便进行关闭。

而CommandBehavior.CloseConnection的功能恰好就是为了避免类似的尴尬境地,它能够保证当SqlDataReader对象被关闭时,其依赖的连接也会被自动关闭。代码9-2展示了使用CommandBehavior.CloseConnection和不使用CommandBehavior.CloseConnection的区别。

这里以SqlDataReader为例进行说明,对于其他命名空间下的XXXDataReader对象,其功能是类似的。

首先为了展示功能,代码9-2包含了两个静态的返回SqlDataReader的方法,其中一个在执行ExecuteReader方法时传入了CommandBehavior.CloseConnection方法class UseCommandBehavior

  1. {
  2.  
  3. //数据库看连接字符串
  4.  
  5. const String conn_String = "Server=localhost;Integrated Security=true;database=NetTest";
  6.  
  7. const String Sql = "select * from dbo.DepartCost";
  1. /// <summary>
  2.  
  3. /// 使用CommandBehavior.CloseConnection
  4. /// </summary>
  5.  
  6. /// <param name="con">为了测试需要,传入连接对象</param>
  7.  
  8. static SqlDataReader GetReader_CloseConnection(SqlConnection con)
  9.  
  10. {
  11.  
  12. try
  13.  
  14. {
  15.  
  16. //打开连接,执行查询
  17.  
  18. //并且返回SqlDataReader
  19.  
  20. con.Open();
  21.  
  22. SqlCommand cmd = con.CreateCommand();
  23.  
  24. cmd.CommandText = Sql;
  25.  
  26. SqlDataReader dr = cmd.ExecuteReader
  27.  
  28. (CommandBehavior.CloseConnection);
  29.  
  30. return dr;
  31.  
  32. }
  33.  
  34. finally
  35.  
  36. {
  37.  
  38. //因为使用了CommandBehavior.CloseConnection,
  39.  
  40. //这里不需要关闭连接
  41.  
  42. //con.Close();
  43.  
  44. }
  45.  
  46. }
  1. /// <summary>
  2.  
  3. /// 不使用CommandBehavior.CloseConnection
  4.  
  5. /// </summary>
  6.  
  7. /// <param name="con">为了测试需要,传入连接对象</param>
  8.  
  9. static SqlDataReader GetReader_NoCloseConnection(SqlConnection con)
  10.  
  11. {
  12.  
  13. try
  14.  
  15. {
  16.  
  17. //打开连接,执行查询
  18.  
  19. //并且返回SqlDataReader
  20.  
  21. con.Open();
  22.  
  23. SqlCommand cmd = con.CreateCommand();
  24.  
  25. cmd.CommandText = Sql;
  26.  
  27. SqlDataReader dr = cmd.ExecuteReader();
  28.  
  29. return dr;
  30.  
  31. }
  32.  
  33. finally
  34.  
  35. {
  36.  
  37. //为了使返回的SqlDataReader可用,这里不能关闭连接
  38.  
  39. //con.Close();
  40.  
  41. }
  42.  
  43. }
  44.  
  45. }
  1.  
  1.  

可以看到,无论是否使用CommandBehavior.CloseConnection,两个方法都没有在最终关闭连接,但是它们不关闭连接的原因并不相同。准备好了两个方法之后,就从主方法中分别调用这两个方法来进行测试,以查看从使用了CommandBehavior.CloseConnection的方法中返回的SqlDataReader对象是否在关闭的同时自动关闭连接,如代码9-3所示。

编写测试方法进行测试:

  1. class UseCommandBehavior
  2.  
  3. {
  4.  
  5. /// <summary>
  6.  
  7. /// 测试方法
  8.  
  9. /// </summary>
  10.  
  11. static void Main(string[] args)
  12.  
  13. {
  14.  
  15. //建立连接
  16.  
  17. SqlConnection con = new SqlConnection(conn_String);
  18.  
  19. try
  20.  
  21. {
  22.  
  23. //测试使用了CommandBehavior.CloseConnection的方法
  24.  
  25. Console.WriteLine("测试使用了CommandBehavior.
  26.  
  27. CloseConnection的方法:");
  28.  
  29. SqlDataReader sdr = GetReader_CloseConnection(con);
  30.  
  31. while (sdr.Read()) { }
  32.  
  33. sdr.Close();
  34.  
  35. Console.WriteLine("读取完毕后的连接状态:" + con.State.ToString());
  36.  
  37. //测试没有使用CommandBehavior.CloseConnection的方法
  38.  
  39. Console.WriteLine("测试没有使用CommandBehavior.
  40.  
  41. CloseConnection的方法:");
  42.  
  43. SqlDataReader sdr1 = GetReader_NoCloseConnection(con);
  44.  
  45. while (sdr1.Read()) { }
  46.  
  47. sdr1.Close();
  48.  
  49. Console.WriteLine("读取完毕后的连接状态:" +
  50.  
  51. con.State.ToString());
  52.  
  53. Console.Read();
  54.  
  55. }
  56.  
  57. finally
  58.  
  59. {
  60.  
  61. //确保连接被关闭
  62.  
  63. if (con.State != ConnectionState.Closed)
  64.  
  65. con.Close();
  66.  
  67. }
  68.  
  69. }
  70.  
  71. }

下面是代码的执行结果:

测试使用了CommandBehavior.CloseConnection的方法:

读取完毕后的连接状态:Closed

测试没有使用CommandBehavior.CloseConnection的方法:

读取完毕后的连接状态:Open

正如读者所看到的,使用了CommandBehavior.CloseConnection得到的SqlDataReader对象,在关闭的同时会自动地关闭其依赖的数据库连接对象,这个特性解决了数据访问层编写中的困境。

答案

CommandBehavior.CloseConnection解决了流读取数据模式下,数据库连接不能有效关闭的情况。当某个XXXDataReader对象在生成时使用了CommandBehavior.CloseConnection,那数据库连接将在XXXDataReader对象关闭时自动关闭。

CommandBehavior.CloseConnection使用的更多相关文章

  1. CommandBehavior.CloseConnection

    cmd.commandTimeout设置为了1秒,sql执行了很长时间还没有超时, cmd.ExecuteReader(CommandBehavior.CloseConnection)这样就会立马重现 ...

  2. cmd.ExecuteReader(CommandBehavior.CloseConnection)

    有些开发人员坚持认为,如果您设置 CommandBehavior.CloseConnection 选项,则 DataReader 及其相关联的连接会在 DataReader 完成数据读取时自动关闭.这 ...

  3. C#使用SqlDataReader读取数据库数据时CommandBehavior.CloseConnection参数的作用

    主要用在ExecuteReader(c)中,如果想要返回对象前不关闭数据库连接,须要用CommandBehavior.CloseConnection: CloseConnection解决了流读取数据模 ...

  4. CommandBehavior.CloseConnection的使用

    CommandBehavior.CloseConnection的使用 分析问题 由于流模式读取数据库的特点,在具体应用时很难确定数据库连接何时才能被关闭,因为读取的动作是连续进行的,下面是一个常见的数 ...

  5. CommandBehavior.CloseConnection有何作用

    其用在ExecuteReader(c)中,返回对象前不能关闭数据库连接,须用CommandBehavior.CloseConnection: 这是一个关于实际知识点的问题,面试官考查的是应聘者数据库访 ...

  6. 浅谈CommandBehavior枚举的独特之处

    提供对查询结果和查询对数据库的影响 此枚举有一个 FlagsAttribute 属性,通过该属性可使其成员值按位组合. 命名空间:  System.Data程序集:  System.Data(在 Sy ...

  7. Microsoft Visual Studio 2017 for Mac Preview 下载+安装+案例Demo

    目录: 0. 前言 1. 在线安装器 2. 安装VS 3. HelloWorld 4. ASP.NET MVC 5. 软件下载 6. 结尾 0. 前言: 工作原因,上下班背着我的雷神,一个月瘦了10斤 ...

  8. 完美解决CodeSmith无法获取MySQL表及列Description说明注释的方案

    问题描述: CodeSmith是现在比较实用的代码生成器,但是我们发现一个问题: 使用CodeSmith编写MySQL模板的时候,会发现一个问题:MySQL数据表中的列说明获取不到,也就是column ...

  9. .NET基础拾遗(6)ADO.NET与数据库开发基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基 ...

随机推荐

  1. vijos——1164 曹冲养猪

    描述 自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把.举个例子,假如有16 ...

  2. Java AOP 获取HttpSevletRequest、HttpSevletResponse、HttpSession对象

    ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) ((ServletRequestAttributes) ...

  3. WINDOW 专家

    http://www.cnblogs.com/shanyou/category/725986.html

  4. Centos7 上安装mysql遇上的问题:mysql无法正常启动

    第一次在Centos上安装mysql遇到的一些问题. 第一步就遇到问题,安装mysql-server报错没有可用包.  [解决方法] 先要安装mysql # wget http://repo.mysq ...

  5. [PsTools]psexec.exe使用范例-运行远程电脑程序(exe、bat等)

    前置条件 先下载psexec.exe.放置到C盘根文件夹 下载地址:http://download.csdn.net/detail/whylaughing/8885893 命令范例:(注意空格) C: ...

  6. 躁动不安的const

    就是用来恐吓你的 我能想到的,最短的.且const最多的一个语句是: int const * fun(int const*const a[],const int index)const; 而这个语句还 ...

  7. apache在windows下的命令安装与报错解决

    1.在windows下能够通过执行apache的exe文件就能够,但当我们打包的时候,就须要命令来安装apache.apache在windows下用命令下的安装为: apache.exe -k ins ...

  8. Cocos2d-x3.3RC0载入Android的WebView

    代码部分摘自http://www.fusijie.com/blog/2013/12/26/play-cocos2dx-33/ Cocos2d-x3.3RC0通过Jni嵌入Android的WebView ...

  9. 关于PROFIBUS Master(H)不能正确识别并处理 DP-Slave 回复的RS帧的一些思考

    图1.是在測试过程中,发现PROFIBUS Master(H)不能正确识别并处理 DP-Slave 回复的RS帧.引起Slave回复 RS 帧的操作是"断开Slave与Master之间的PR ...

  10. C++ 函数模板与类模板(使用 Qt 开发编译环境)

    注意:本文中代码均使用 Qt 开发编译环境,如有疑问和建议欢迎随时留言. 模板是 C++ 支持参数化程序设计的工具,通过它可以实现参数多态性.所谓参数多态性,就是将程序所处理的对象的类型参数化,使得一 ...