zoukankan      html  css  js  c++  java
  • DataReader和DataAdapter的区别

    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可以读取完数据库后自动断开连接.

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

     使用20万条数据进行测试

    ExecuteReader耗时50秒,
    OracleDataAdapter耗时11秒
    测试如下
     Stopwatch watch = Stopwatch.StartNew();
                watch.Start();
    
                List<BOARD_VEHICLE_DAY_INFOEntity> list = new List<BOARD_VEHICLE_DAY_INFOEntity>();
                List<BOARD_VEHICLE_DAY_INFOEntity> list1 = new List<BOARD_VEHICLE_DAY_INFOEntity>();
                List<BOARD_VEHICLE_DAY_INFOEntity> list2 = new List<BOARD_VEHICLE_DAY_INFOEntity>();
                List<BOARD_VEHICLE_DAY_INFOEntity> list3 = new List<BOARD_VEHICLE_DAY_INFOEntity>();
                Task wt1 = Task.Run(() =>
                {
                    list1 = test1();
                    list.AddRange(list1);
                });
                Task wt2 = Task.Run(() =>
                {
                    list2 = test2();
                    list.AddRange(list2);
                });
                Task wt3 = Task.Run(() =>
                {
                    list3 = test3();
                    list.AddRange(list3);
                });
                var wtasks = new Task[] { wt1, wt2, wt3 };
                Task.WaitAll(wtasks);
                watch.Stop();
                Console.WriteLine($"耗时:{watch.ElapsedMilliseconds},总数:{list.Count}");
                Console.ReadKey();
     static private List<BOARD_VEHICLE_DAY_INFOEntity> test1()
            {
                List<BOARD_VEHICLE_DAY_INFOEntity> list = new List<BOARD_VEHICLE_DAY_INFOEntity>();
                DataTable result = new DataTable();
                var sql = "SELECT *  FROM  BOARD_VEHICLE_DAY_INFO  WHERE PASSKEY LIKE '豫%' ";
                //ExecuteReader
                using (OracleConnection conn = new OracleConnection("Data Source=zhzepp;User Id=jxlx;Password=citms;"))
                {
                    conn.Open();
                    //创建命令对象,前面一个表示执行的语句,后面一个表示执行语句需要连接的数据库
                    OracleCommand cmd = new OracleCommand(sql, conn);
                    //创建查询的结果集,用另一个封装的方法,ExecuteReader
                    //OracleDataReader read = cmd.ExecuteReader();
                    //result.Load(read);
                    OracleDataAdapter adapter = new OracleDataAdapter(cmd);
                    adapter.Fill(result);
                    conn.Close();
                    list = ConvertToModel<BOARD_VEHICLE_DAY_INFOEntity>(result);
                }
                return list;
            }
            static private List<BOARD_VEHICLE_DAY_INFOEntity> test2()
            {
                List<BOARD_VEHICLE_DAY_INFOEntity> list = new List<BOARD_VEHICLE_DAY_INFOEntity>();
                DataTable result = new DataTable();
                var sql = "SELECT *  FROM  BOARD_VEHICLE_DAY_INFO  WHERE PASSKEY  LIKE '湘%' ";
                //ExecuteReader
                using (OracleConnection conn = new OracleConnection("Data Source=zhzepp;User Id=jxlx;Password=citms;"))
                {
                    conn.Open();
                    //创建命令对象,前面一个表示执行的语句,后面一个表示执行语句需要连接的数据库
                    OracleCommand cmd = new OracleCommand(sql, conn);
                    //创建查询的结果集,用另一个封装的方法,ExecuteReader
                    //OracleDataReader read = cmd.ExecuteReader();
                    //result.Load(read);
                    OracleDataAdapter adapter = new OracleDataAdapter(cmd);
                    adapter.Fill(result);
                    conn.Close();
                    list = ConvertToModel<BOARD_VEHICLE_DAY_INFOEntity>(result);
                }
                return list;
            }
            static private List<BOARD_VEHICLE_DAY_INFOEntity> test3()
            {
                List<BOARD_VEHICLE_DAY_INFOEntity> list = new List<BOARD_VEHICLE_DAY_INFOEntity>();
                DataTable result = new DataTable();
                var sql = "SELECT *  FROM  BOARD_VEHICLE_DAY_INFO  WHERE PASSKEY  LIKE '鄂%' ";
                //ExecuteReader
                using (OracleConnection conn = new OracleConnection("Data Source=zhzepp;User Id=jxlx;Password=citms;"))
                {
                    conn.Open();
                    //创建命令对象,前面一个表示执行的语句,后面一个表示执行语句需要连接的数据库
                    OracleCommand cmd = new OracleCommand(sql, conn);
                    //创建查询的结果集,用另一个封装的方法,ExecuteReader
                    //OracleDataReader read = cmd.ExecuteReader();
                    //result.Load(read);
                    OracleDataAdapter adapter = new OracleDataAdapter(cmd);
                    adapter.Fill(result);
                    conn.Close();
                    list = ConvertToModel<BOARD_VEHICLE_DAY_INFOEntity>(result);
                }
                return list;
            }
            /// <summary>
            /// 将DataTable数据源转换成实体类
            /// </summary>
            public static List<T> ConvertToModel<T>(DataTable dt) where T : new()
            {
                List<T> ts = new List<T>();// 定义集合
                foreach (DataRow dr in dt.Rows)
                {
                    T t = new T();
                    PropertyInfo[] propertys = t.GetType().GetProperties();// 获得此模型的公共属性
                    foreach (PropertyInfo pi in propertys)
                    {
                        if (dt.Columns.Contains(pi.Name))
                        {
                            if (!pi.CanWrite) continue;
                            var value = dr[pi.Name];
                            try
                            {
                                if (value != DBNull.Value && value != null && value.ToString() != "")
                                {
                                    if (pi.PropertyType.FullName.ToUpper().Contains("DECIMAL"))
                                    {
                                        pi.SetValue(t, decimal.Parse(value.ToString()), null);
                                    }
                                    else if (pi.PropertyType.FullName.ToUpper().Contains("DOUBLE"))
                                    {
                                        pi.SetValue(t, double.Parse(value.ToString()), null);
                                    }
                                    else if (pi.PropertyType.FullName.ToUpper().Contains("INT32"))
                                    {
                                        pi.SetValue(t, int.Parse(value.ToString()), null);
                                    }
                                    else if (pi.PropertyType.FullName.ToUpper().Contains("INT16"))
                                    {
                                        pi.SetValue(t, short.Parse(value.ToString()), null);
                                    }
                                    else
                                        pi.SetValue(t, value, null);
    
                                }
                            }
                            catch (Exception ex)
                            {
                                //throw ex;
                            }
    
                        }
                    }
                    ts.Add(t);
                }
                return ts;
            }
  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/macT/p/11759493.html
Copyright © 2011-2022 走看看