看了關於DataReader的擴展,發現能節省很多代碼。從數據庫讀取數據最原始方法就是while()然后做循環,如果數據庫添加一個字段那么你所有讀取數據庫的方法全部添加。通過擴展這個類就擺脫了這種令人惡心的方式,關於效率我進行測試,當讀取不多的時候效率相差不大,當讀取幾十萬條而至數百萬的時候可能效率就不如手寫這種普通的方式,大家如果有興趣可以自己去測試。好了,開始寫
我先貼一張比較難看的圖
但是這就是轉換的一個過程:我貼代碼
1:
/// <summary> /// 將數據轉換為實體集合 /// </summary> /// <typeparam name="T">類型</typeparam> /// <param name="dr">DbDataReader對象</param> /// <returns>實體集合</returns> /// <remarks></remarks> public static List<T> ToEntitys<T>(this IDataReader dr) where T : new() { if (dr == null) return null; var type = typeof(T);//獲取實體類型 var hs = new Hashtable();//目的存所有實體的屬性 var propts = type.GetProperties();//獲取所有實體屬性 foreach (var info in propts)//存入hash表中 { hs[info.Name.ToUpper()] = info; } var entitys = new List<T>(); while (dr.Read()) { var t = new T(); for (var index = 0; index < dr.FieldCount; index++) { var info = (PropertyInfo) hs[dr.GetName(index).ToUpper()];//從dr中讀取字段,然后看hash表中是否存在此屬性 if ((info == null) || !info.CanWrite) continue;//如果沒有或者不可寫則繼續 var data = dr.GetValue(index);//獲取屬性值 var dType = data.GetType();//獲取屬性類型 if (dType == typeof (Guid)) info.SetValue(t, data == DBNull.Value ? null : data.ToString(), null);//把Guid轉換成string else info.SetValue(t, data == DBNull.Value ? null : data, null); } entitys.Add(t); } dr.Close();//關閉流 return entitys; }
注釋1:this就表示擴展這個類(我的理解)
注釋2:SetValue() 這個就是填充值的。t是我們的實體類,data是屬性值,通過這種方式把值賦給類對應的屬性(映射)比喻一個實體類User的一個屬性Name,然后dr讀取數據庫對象也存在Name這樣一來就對應上了,然后在進行賦值。
2:進行測試
第一步:我插入數據庫14萬條數據
第二步:用普通方式讀取10條
/// <summary> /// 常規讀取數據庫 /// </summary> [Test] public void CommonReadTest() { string StrSql = "select top 10 * from DataReaderDB"; SqlDataReader reader = DbHelperSQL.ExecuteReader("", CommandType.Text, StrSql, null); List<UserInfo> userInfos=new List<UserInfo>(); while (reader.Read()) { UserInfo user =new UserInfo(); user.Id = reader["Id"].ToString(); int age = 0; user.Age = int.TryParse(reader["Age"].ToString(), out age) ? age : 0; user.Name = reader["Name"].ToString(); user.Title = reader["Title"].ToString(); user.RealName = reader["RealName"].ToString(); user.DContent = reader["DContent"].ToString(); user.Systime = DateTime.Parse(reader["Systime"].ToString()); userInfos.Add(user); } Assert.AreEqual(10, userInfos.Count); }
運行速度(第一次由於加載導致慢。所以我選取的不是第一次,你可以多測幾次)
第三步:擴展方式讀取10條
/// <summary> /// 擴展流讀取數據庫 /// </summary> [Test] public void ExtensionReadTest() { string StrSql = "select top 10 * from DataReaderDB"; SqlDataReader reader = DbHelperSQL.ExecuteReader("", CommandType.Text, StrSql, null); List<UserInfo> userInfos = reader.ToEntitys<UserInfo>(); Assert.AreEqual(10, userInfos.Count); }
第四步:普通方式讀取14萬條(只貼效果圖)
第五步:擴展方式讀取14萬條
總結:從中我們可以看出當數據量越來越大的時候擴展就相對來說慢些,當時數量不大兩者相差不大,反而擴展更快,也許我測的不准,可以自己測試(注意第一次加載可能導致慢一定多測試幾次),我個人覺得如果不是太考慮效率應該用擴展,因為便於項目的維護(最后注意數據庫字段和實體類屬性記得保持一致)