SqlDataReader是一个向前的指针,本身并不包含数据,调用一次Read()方法它就向前到下一条记录,一个SqlDataReader必须单独占用一个打开的数据库连接。

在使用 SqlDataReader时,关联的 SqlConnection 正忙于为 SqlDataReader 服务,对 SqlConnection 无法执行任何其他操作。除非调用 SqlDataReader 的 Close 方法,否则会一直处于此状态。

SqlDataAdapter象一座桥梁,一头连起数据库表,一头连起一个 DataSet 或者 DataTable ,在把数据库中的数据填充到 DataSet 或 DataTable 后就可以“过河拆桥”,不用再连接到数据库,而可以直接从 DataSet 或 DataTable 中获取数据。

SqlDataAdapter提供了许多的方法,来方便我们对一些特定的数据集合进行操作比如,填充一个查询结果到 DataTable ,或 DataSet 中其实就是类似于:创建一个 SqlCommand 然后执行 "Select * from [Table]" 然后执行 ExcuteReader()方法 得到一个IDataReader对象然后逐行读取数据并存放到一个集合对象中(如DataTable)经过测试,如果有大量的数据操作最好是自己写 SqlCommand ,会比SqlDataAdapter操作数据库快很多

SqlDataReader只能读取数据库,而且所操作的表必须处于连接状态,但是要对数据库进行写操时,只能借助 SqlCommand 类,SqlDataAdapter 它建立在 SqlCommand 对象之上,它具有 SqlCommand 类的一切功能,能够将数据填充到 DataSet 对象中,而且不用再连接到数据库,而可以直接从 DataSet 或 DataTable 中获取数据。(因为它采用的无连接传输模式)

SqlDataReader对象可以从数据库中得到只读的、只能向前的数据流,还可以提高应用程序的性能,减少系统开销,同一时间只有一条行记录在内存中。

SqlDataAdapter对象可以自动打开和自动关闭数据库连接(不需人为管理),适配器的主要工作流程:SqlConnection 对象建立与数据源的连接,SqlDataAdapter 对象经由 SqlCommand 对象返回给SqlDataAdapter,最后将SqlDataAdapter对象加入到 DataSet 对象的 DataTables 对象中。

总结:

性能上:SqlDataReader一次只在内存中存储一行,减少了系统开销。优于SqlDataAdapter。

读取时:SqlDataReader需通过调用自身Read()方法循环读取数据到指定对象。而SqlDataAdapter可通过调用Fill()方法一次性填充数据到DataSet。还可将对 DataSet 所做的更改解析回数据源。

操作上:SqlDataReader需通过调用自身的Close()方法断开连接。而SqlDataAdapter可以读取完数据库后自动断开连接.

  1. var sql = "SELECT * FROM BOARD_VEHICLE_DAY_INFO WHERE PASSKEY='湘ALM2DA-2-2019年10月15日' ";
     DataTable result = new DataTable();
  2. //ExecuteReader
  3. using (OracleConnection conn = new OracleConnection("Data Source=zhzepp;User Id=jxlx;Password=citms;"))
  4. {
  5. conn.Open();
  6. //创建命令对象,前面一个表示执行的语句,后面一个表示执行语句需要连接的数据库
  7. OracleCommand cmd = new OracleCommand(sql, conn);
  8. //创建查询的结果集,用另一个封装的方法,ExecuteReader
  9. OracleDataReader read = cmd.ExecuteReader();
  10. result.Load(read);
  11. }
  12. //OracleDataAdapter
  13. using (OracleConnection conn = new OracleConnection("Data Source=zhzepp;User Id=jxlx;Password=citms;"))
  14. {
  15. conn.Open();
  16. //创建命令对象,前面一个表示执行的语句,后面一个表示执行语句需要连接的数据库
  17. OracleCommand cmd = new OracleCommand(sql, conn);
  18. OracleDataAdapter adapter = new OracleDataAdapter(cmd);
  19. adapter.Fill(result);
  20. }

使用20万条数据进行测试

  1. ExecuteReader耗时50秒,
  1. OracleDataAdapter耗时11
    测试如下
  1. Stopwatch watch = Stopwatch.StartNew();
  2. watch.Start();
  3.  
  4. List<BOARD_VEHICLE_DAY_INFOEntity> list = new List<BOARD_VEHICLE_DAY_INFOEntity>();
  5. List<BOARD_VEHICLE_DAY_INFOEntity> list1 = new List<BOARD_VEHICLE_DAY_INFOEntity>();
  6. List<BOARD_VEHICLE_DAY_INFOEntity> list2 = new List<BOARD_VEHICLE_DAY_INFOEntity>();
  7. List<BOARD_VEHICLE_DAY_INFOEntity> list3 = new List<BOARD_VEHICLE_DAY_INFOEntity>();
  8. Task wt1 = Task.Run(() =>
  9. {
  10. list1 = test1();
  11. list.AddRange(list1);
  12. });
  13. Task wt2 = Task.Run(() =>
  14. {
  15. list2 = test2();
  16. list.AddRange(list2);
  17. });
  18. Task wt3 = Task.Run(() =>
  19. {
  20. list3 = test3();
  21. list.AddRange(list3);
  22. });
  23. var wtasks = new Task[] { wt1, wt2, wt3 };
  24. Task.WaitAll(wtasks);
  25. watch.Stop();
  26. Console.WriteLine($"耗时:{watch.ElapsedMilliseconds},总数:{list.Count}");
  27. Console.ReadKey();
  1. static private List<BOARD_VEHICLE_DAY_INFOEntity> test1()
  2. {
  3. List<BOARD_VEHICLE_DAY_INFOEntity> list = new List<BOARD_VEHICLE_DAY_INFOEntity>();
  4. DataTable result = new DataTable();
  5. var sql = "SELECT * FROM BOARD_VEHICLE_DAY_INFO WHERE PASSKEY LIKE '豫%' ";
  6. //ExecuteReader
  7. using (OracleConnection conn = new OracleConnection("Data Source=zhzepp;User Id=jxlx;Password=citms;"))
  8. {
  9. conn.Open();
  10. //创建命令对象,前面一个表示执行的语句,后面一个表示执行语句需要连接的数据库
  11. OracleCommand cmd = new OracleCommand(sql, conn);
  12. //创建查询的结果集,用另一个封装的方法,ExecuteReader
  13. //OracleDataReader read = cmd.ExecuteReader();
  14. //result.Load(read);
  15. OracleDataAdapter adapter = new OracleDataAdapter(cmd);
  16. adapter.Fill(result);
  17. conn.Close();
  18. list = ConvertToModel<BOARD_VEHICLE_DAY_INFOEntity>(result);
  19. }
  20. return list;
  21. }
  22. static private List<BOARD_VEHICLE_DAY_INFOEntity> test2()
  23. {
  24. List<BOARD_VEHICLE_DAY_INFOEntity> list = new List<BOARD_VEHICLE_DAY_INFOEntity>();
  25. DataTable result = new DataTable();
  26. var sql = "SELECT * FROM BOARD_VEHICLE_DAY_INFO WHERE PASSKEY LIKE '湘%' ";
  27. //ExecuteReader
  28. using (OracleConnection conn = new OracleConnection("Data Source=zhzepp;User Id=jxlx;Password=citms;"))
  29. {
  30. conn.Open();
  31. //创建命令对象,前面一个表示执行的语句,后面一个表示执行语句需要连接的数据库
  32. OracleCommand cmd = new OracleCommand(sql, conn);
  33. //创建查询的结果集,用另一个封装的方法,ExecuteReader
  34. //OracleDataReader read = cmd.ExecuteReader();
  35. //result.Load(read);
  36. OracleDataAdapter adapter = new OracleDataAdapter(cmd);
  37. adapter.Fill(result);
  38. conn.Close();
  39. list = ConvertToModel<BOARD_VEHICLE_DAY_INFOEntity>(result);
  40. }
  41. return list;
  42. }
  43. static private List<BOARD_VEHICLE_DAY_INFOEntity> test3()
  44. {
  45. List<BOARD_VEHICLE_DAY_INFOEntity> list = new List<BOARD_VEHICLE_DAY_INFOEntity>();
  46. DataTable result = new DataTable();
  47. var sql = "SELECT * FROM BOARD_VEHICLE_DAY_INFO WHERE PASSKEY LIKE '鄂%' ";
  48. //ExecuteReader
  49. using (OracleConnection conn = new OracleConnection("Data Source=zhzepp;User Id=jxlx;Password=citms;"))
  50. {
  51. conn.Open();
  52. //创建命令对象,前面一个表示执行的语句,后面一个表示执行语句需要连接的数据库
  53. OracleCommand cmd = new OracleCommand(sql, conn);
  54. //创建查询的结果集,用另一个封装的方法,ExecuteReader
  55. //OracleDataReader read = cmd.ExecuteReader();
  56. //result.Load(read);
  57. OracleDataAdapter adapter = new OracleDataAdapter(cmd);
  58. adapter.Fill(result);
  59. conn.Close();
  60. list = ConvertToModel<BOARD_VEHICLE_DAY_INFOEntity>(result);
  61. }
  62. return list;
  63. }
  64. /// <summary>
  65. /// 将DataTable数据源转换成实体类
  66. /// </summary>
  67. public static List<T> ConvertToModel<T>(DataTable dt) where T : new()
  68. {
  69. List<T> ts = new List<T>();// 定义集合
  70. foreach (DataRow dr in dt.Rows)
  71. {
  72. T t = new T();
  73. PropertyInfo[] propertys = t.GetType().GetProperties();// 获得此模型的公共属性
  74. foreach (PropertyInfo pi in propertys)
  75. {
  76. if (dt.Columns.Contains(pi.Name))
  77. {
  78. if (!pi.CanWrite) continue;
  79. var value = dr[pi.Name];
  80. try
  81. {
  82. if (value != DBNull.Value && value != null && value.ToString() != "")
  83. {
  84. if (pi.PropertyType.FullName.ToUpper().Contains("DECIMAL"))
  85. {
  86. pi.SetValue(t, decimal.Parse(value.ToString()), null);
  87. }
  88. else if (pi.PropertyType.FullName.ToUpper().Contains("DOUBLE"))
  89. {
  90. pi.SetValue(t, double.Parse(value.ToString()), null);
  91. }
  92. else if (pi.PropertyType.FullName.ToUpper().Contains("INT32"))
  93. {
  94. pi.SetValue(t, int.Parse(value.ToString()), null);
  95. }
  96. else if (pi.PropertyType.FullName.ToUpper().Contains("INT16"))
  97. {
  98. pi.SetValue(t, short.Parse(value.ToString()), null);
  99. }
  100. else
  101. pi.SetValue(t, value, null);
  102.  
  103. }
  104. }
  105. catch (Exception ex)
  106. {
  107. //throw ex;
  108. }
  109.  
  110. }
  111. }
  112. ts.Add(t);
  113. }
  114. return ts;
  115. }

DataReader和DataAdapter的区别的更多相关文章

  1. ADO.NET DataReader和DataAdapter的区别

    SqlDataReader是一个向前的指针,本身并不包含数据,调用一次 Read() 方法它就向前到下一条记录,一个SqlDataReader必须单独占用一个打开的数据库连接. 在使用 SqlData ...

  2. Data Base sqlServer DataReader与DataSet的区别

    sqlServer   DataReader与DataSet的区别 从以下这几个方面比较: 1.与数据库连接: DataReader:面向连接,只读,只进,只能向前读,读完数据就断开连接: DataS ...

  3. Winform开发之ADO.NET对象Connection、Command、DataReader、DataAdapter、DataSet和DataTable简介

    ADO.NET技术主要包括Connection.Command.DataReader.DataAdapter.DataSet和DataTable等6个对象,下面对这6个对象进行简单的介绍:(1)Con ...

  4. sqlServer DataReader与DataSet的区别

    sqlServer   DataReader与DataSet的区别 从以下这几个方面比较: 1.与数据库连接: DataReader:面向连接,只读,只进,只能向前读,读完数据就断开连接: DataS ...

  5. DataReader 和 DataSet 的区别

    摘自:http://www.cnblogs.com/zhjjNo1/archive/2009/08/26/1554420.html 第一种解释 DataReader和DataSet最大的区别在于,Da ...

  6. C# 之 DataReader 和 DataSet 的区别

    本文转载自:http://www.cnblogs.com/xinaixia/p/4920630.html 1. 获取数据的方式[1]DataReader 为在线操作数据, DataReader会一直占 ...

  7. DataReader和DataSet的区别以及使用

    DataReader和DataSet这两个对象都可以将检索的关系数据存储在内存中.它们在功能使用方面非常相似,但是它们不可以相互替换. 主要区别如表所示:   DataReader DataSet 数 ...

  8. Sql Server + ADO.NET

    MsSql-http://www.cnblogs.com/zhangwei595806165/archive/2012/02/23/2364746.html 协议:Shared Memory :效率最 ...

  9. datareader 和dataset 区别

    ADO.NET2.0提供了两个用于检索关系数据的对象:DataSet和DataReader.并且这两个对象都可以将检索的关系数据存储在内存中.在软件开发过程中经常用到这两个控件,由于这两个控件在使用和 ...

随机推荐

  1. cssdiv设置高宽百分比不起作用的问题

    div等元素设置宽高百分比都是基于包含他的块级对象的百分比高度,所以必须先设置包含它的块级对象高度与宽度,但是光设置body是不起作用的,必须同时设置html和body.   要使用百分比设置div宽 ...

  2. Latin-1字符集

    ISO Latin-1字符集是Unicode字符集的一个子集,对应于IE4+中Unicode字符指令表的前256个条目.下面表格中详细提供了每个字符及字符的十进制编码和HTML已命名实体.其中Unic ...

  3. spring boot 整合mapreduce运行的ClassNotFoundException

    问题 一个wordcount运行总是报错 java.lang.RuntimeException: java.lang.ClassNotFoundException: Class com.hadoop. ...

  4. Ubuntu配置Python开发环境(PyCharm、Tensorflow)

    安装JDK: https://www.cnblogs.com/wanghuixi/p/9837229.html 安装Anaconda: 安装PyCharm: https://www.cnblogs.c ...

  5. input和button 高度不一致问题

    原因是 input和button的高度计算不一样, input高度不包括border. button高度包括border. 解决方法: 1.box-sizing:border-box: 2.borde ...

  6. 使用IDEA导入一个Maven风格的SSM项目

    转自: 方法一: (我用的这种,导入的方法 File->New->Project from existing sources)(同理,important也是一样的) https://how ...

  7. redhat7.6 DNS配置正向解析

    1.安装DNS服务 yum install bind yum install bind-chroot 安装完的配置文件/etc/named.conf 启动systemctl start named.s ...

  8. vector的使用-Hdu 4841

    圆桌问题 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submis ...

  9. 「NOI2006」最大获利

    「NOI2006」最大获利 传送门 最小割. 对于每一组用户群 \(A_i, B_i, C_i\) ,连边 $S \to A_i, S \to B_i, $ 容量为成本,还有 \(i \to T\) ...

  10. Python 中命令行参数解析工具 docopt 安装和应用

    什么是 docopt? 1.docopt 是一种 Python 编写的命令行执行脚本的交互语言. 它是一种语言! 它是一种语言! 它是一种语言! 2.使用这种语言可以在自己的脚本中,添加一些规则限制. ...