【原创】编程日记之——如何对DataSet进行强类型化
2011-04-12 15:28 刺客之家 阅读(1741) 评论(8) 编辑 收藏 举报前言
在项目中经常需要用到DataSet来存放数据,但是一直觉得从数据集中获取数据使用是一件很难受的事情,特别是当需要用到强类型数据的时候,就想到了动手写个方法来实现。
正文
废话不多说,直接上代码吧:
/// <summary> /// 将数据集强类型化 /// </summary> /// <typeparam name="T">转换类型</typeparam> /// <param name="dataSet">数据源</param> /// <param name="tableIndex">需要转换表的索引</param> /// <returns>泛型集合</returns> public static IList<T> ToList<T>(this DataSet dataSet, int tableIndex) { //确认参数有效 if (dataSet == null || dataSet.Tables.Count <= 0 || tableIndex < 0||dataSet.Tables.Count <= tableIndex) return null; DataTable dt = dataSet.Tables[tableIndex]; IList<T> list = new List<T>(); for (int i = 0; i < dt.Rows.Count; i++) { //创建泛型对象 T _t = Activator.CreateInstance<T>(); //获取对象所有属性 PropertyInfo[] propertyInfo = _t.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); for (int j = 0; j < dt.Columns.Count; j++) { foreach (PropertyInfo info in propertyInfo) { //属性名称和列名相同时赋值 if (dt.Columns[j].ColumnName.ToUpper().Equals(info.Name.ToUpper())) { if (dt.Rows[i][j] != DBNull.Value) { info.SetValue(_t, dt.Rows[i][j].ConvertDataTo(info.PropertyType), null); } else { info.SetValue(_t, null, null); } break; } } } list.Add(_t); } return list; }
在需要给属性赋值的时候,为了避免数据集中的字段名与用户定义的Model属性名一致而类型不一致的问题,我又写了个方法,用来把对象进行类型转换:
public static object ConvertDataTo(this object obj,Type type) { if (obj.GetType().Equals(type)) { return obj; } else { try { if (type == typeof(string)) { return obj.ToString(); } MethodInfo parseMethod = null; foreach (MethodInfo mi in type.GetMethods(BindingFlags.Static | BindingFlags.Public)) { if (mi.Name == "Parse" && mi.GetParameters().Length == 1) { parseMethod = mi; break; } } if (parseMethod == null) { return null; } return parseMethod.Invoke(null, new object[] { obj }); } catch { return null; } } }
其实这么写是比较偷懒的写法,用了这么多反射, 于是想到做一下性能测试,我建的MVC项目,看一下测试结果:
public ActionResult Index() { DataSet ds = new DataSet(); DataTable dt = new DataTable(); dt.Columns.Add("resourcename1", typeof(string)); dt.Columns.Add("resourcename2", typeof(string)); dt.Columns.Add("resourcename3", typeof(string)); dt.Columns.Add("resourcename4", typeof(string)); dt.Columns.Add("resourcename5", typeof(string)); dt.Columns.Add("fitsex1", typeof(int)); dt.Columns.Add("fitsex2", typeof(int)); dt.Columns.Add("fitsex3", typeof(int)); dt.Columns.Add("fitsex4", typeof(int)); dt.Columns.Add("fitsex5", typeof(int)); for (int i = 0; i < 5000; i++) { DataRow row = dt.NewRow(); row[0] = "王虎" + i.ToString(); row[1] = "王虎" + i.ToString(); row[2] = "王虎" + i.ToString(); row[3] = "王虎" + i.ToString(); row[4] = "王虎" + i.ToString(); row[5] = i; row[6] = i; row[7] = i; row[8] = i; row[9] = i; dt.Rows.Add(row); } ds.Tables.Add(dt); var watch = new Stopwatch(); watch.Start(); var ModelList = ds.ToList<Model_Resource>(0); watch.Stop(); ViewData["Message"] = string.Format("ModelList.count={0},Elapsed Milliseconds:{1}", ModelList.Count.ToString(),watch.ElapsedMilliseconds.ToString()); return View(); }
我使用的类定义如下:
/// <summary> /// 实体类Resource 。(属性说明自动提取数据库字段的描述信息) /// </summary> [Serializable] public class Model_Resource { public Model_Resource() { } #region Model /// <summary> /// 资源标准名称 /// </summary> public string ResourceName1 { get; set; } /// <summary> /// 资源标准名称 /// </summary> public string ResourceName2 { get; set; } /// <summary> /// 资源标准名称 /// </summary> public string ResourceName3 { get; set; } /// <summary> /// 资源标准名称 /// </summary> public string ResourceName4 { get; set; } /// <summary> /// 资源标准名称 /// </summary> public string ResourceName5 { get; set; } /// <summary> /// 适合的性别 1 男 2 女 3 均可 /// </summary> public string FitSex1 { get; set; } /// <summary> /// 适合的性别 1 男 2 女 3 均可 /// </summary> public string FitSex2 { get; set; } /// <summary> /// 适合的性别 1 男 2 女 3 均可 /// </summary> public string FitSex3 { get; set; } /// <summary> /// 适合的性别 1 男 2 女 3 均可 /// </summary> public string FitSex4 { get; set; } /// <summary> /// 适合的性别 1 男 2 女 3 均可 /// </summary> public string FitSex5 { get; set; } #endregion Model }
看一下测试结果:
后记
性能上还可以通过缓存等机制优化一下,不过这方面已经有一些大牛做过了,以后有时间可以加进去。
欢迎拍砖~