多年前写的DataTable与实体类的转换,已放github
本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。
文章是哥(mephisto)写的,SourceLink
阅读目录
本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。
文章是哥(mephisto)写的,SourceLink
介绍
很多年前一直使用Ado.net,后来慢慢转型到其他的orm,在转型过程中,有意向将两者的模型结合起来,利用DataTable中的行状态完善一些mvc中的数据控制作用。现在把它放出来,留个纪念。
起因
很多年前,对Ado.net这块了解较深,当时公司也有一套框架,将Ado.net做成了ORMapping,所以,当时对DataTable的操作很是熟练。
DataTable中的行状态很好的和界面的数据后者操作进行了关联,比如新增,修改,取消,删除等,都能在DataTable中的行状态对应起来,然后那个orm框架就自动根据不同的行状态生成sql语句,也是比较方便。
后来,技术一直在进步,也使用过EF,使用过java移植过来的Nhibernate,这样对实体类的操作越来越多,当时就产生了这样一个想法,界面绑定DataTable,然后数据的变动通过这些新的orm工具持久化起来,于是就做了这个工具类。
代码
因为是工具类,代码结构比较简单。如图:
TransformUtil工具类主要就3个方法。
一:ConvertDataTableToModel:
主要将DataTable中改动的内容同步到实体类集合中
- /// <summary>
- /// 将DB中改动的内容同步到泛型集合中
- /// </summary>
- /// <typeparam name="T">类型</typeparam>
- /// <param name="source">dt源</param>
- /// <param name="destinationArray">目标Model集合</param>
- /// <returns></returns>
- public static bool ConvertDataTableToModel<T>(DataTable source, List<T> destinationArray)
- where T : class
- {
- if (source == null || destinationArray == null || source.PrimaryKey == null || source.PrimaryKey.Count() <= )
- return false;
- DataTable dtChange = source.GetChanges();
- if (dtChange == null)
- return false;
- List<string> keys = new List<string>();
- foreach (var item in source.PrimaryKey)
- {
- keys.Add(item.ColumnName);
- }
- return ConvertDataTableToModel(source, destinationArray, keys);
- }
二:ConvertDataTableToModel重载:
- /// <summary>
- /// 同步table里改动的数据到泛型集合里去(新增,修改,删除)
- /// </summary>
- /// <typeparam name="T">类型</typeparam>
- /// <param name="source">dt源</param>
- /// <param name="destinationArray">目标Model集合</param>
- /// <param name="keyColumnArray">主键集合</param>
- /// <returns></returns>
- public static bool ConvertDataTableToModel<T>(DataTable source, List<T> destinationArray, List<string> keyColumnArray)
- where T : class
- {
- if (source == null || destinationArray == null || source.Rows.Count == || keyColumnArray == null || keyColumnArray.Count == )
- return false;
- Type modeType = destinationArray.GetType().GetGenericArguments()[];//模型类型
- PropertyInfo[] ppInfoArray = modeType.GetProperties();//公共属性集合
- List<PropertyInfo> listPPInfo = ppInfoArray.ToList();//方便查询
- //关键列
- List<PropertyInfo> keyPIArray = listPPInfo.FindAll(x => keyColumnArray.Contains(x.Name));
- List<T> listToDelete = new List<T>();
- //新增的数据
- DataRow[] drAddArray = source.Select("", "", DataViewRowState.Added);
- object objItem = modeType.Assembly.CreateInstance(modeType.FullName);
- foreach (DataRow dr in drAddArray)
- {
- destinationArray.Add((T)objItem);
- foreach (System.Reflection.PropertyInfo pi in listPPInfo)
- {
- pi.SetValue(destinationArray[destinationArray.Count - ], dr[pi.Name], null);
- }
- }
- //修改和删除的数据
- DataView dvForOP = new DataView(source);
- dvForOP.RowStateFilter = DataViewRowState.Deleted | DataViewRowState.ModifiedCurrent;
- foreach (DataRowView drv in dvForOP)
- {
- for (int i = ; i < destinationArray.Count; i++)
- {
- bool blIsTheRow = true;
- //找出关键列对应的行
- foreach (System.Reflection.PropertyInfo pInfo in keyPIArray)
- {
- object okey = pInfo.GetValue(destinationArray[i], null);
- if (okey == null)
- continue;
- if (drv[pInfo.Name].ToString() != okey.ToString())
- {
- blIsTheRow = false;
- break;
- }
- }
- if (!blIsTheRow)//非本行
- continue;
- //根据行状态同步赋值
- switch (drv.Row.RowState)
- {
- case DataRowState.Modified:
- {
- foreach (System.Reflection.PropertyInfo pi in listPPInfo)
- {
- if (keyPIArray.Contains(pi))//主键列不更新
- continue;
- pi.SetValue(destinationArray[i], drv[pi.Name], null);
- }
- } break;
- case DataRowState.Deleted:
- {
- listToDelete.Add(destinationArray[i]);
- } break;
- }
- }
- }
- for (int i = ; i < listToDelete.Count; i++)
- {
- destinationArray.Remove(listToDelete[i]);
- }
- return true;
- }
三:ConvertModelToDataTable:
将实体类集合转成DataTable。其中params这个参数比较有意思,大家可以去查下。
- /// <summary>
- /// 将泛型集合类转换成DataTable
- /// </summary>
- /// <typeparam name="T">集合项类型</typeparam>
- /// <param name="sourceArray">集合</param>
- /// <param name="propertyNameArray">需要返回的列的列名,如需返回所有列,此参数传入null值</param>
- /// <returns>数据集(表)</returns>
- public static DataTable ConvertModelToDataTable<T>(IList<T> sourceArray, params string[] propertyNameArray)
- where T:class
- {
- List<string> propertyNameList = new List<string>();
- if (propertyNameArray != null)
- propertyNameList.AddRange(propertyNameArray);
- DataTable result = new DataTable();
- //获取结构
- Type[] typeArr = sourceArray.GetType().GetGenericArguments();
- if (typeArr.Length == )
- return result;
- PropertyInfo[] propertys = typeArr[].GetProperties();
- foreach (PropertyInfo pi in propertys)
- {
- if (propertyNameList.Count == )
- {
- result.Columns.Add(pi.Name, pi.PropertyType);
- }
- else
- {
- if (propertyNameList.Contains(pi.Name))
- result.Columns.Add(pi.Name, pi.PropertyType);
- }
- }
- for (int i = ; i < sourceArray.Count; i++)
- {
- ArrayList tempList = new ArrayList();
- foreach (PropertyInfo pi in propertys)
- {
- if (propertyNameList.Count == )
- {
- object obj = pi.GetValue(sourceArray[i], null);
- tempList.Add(obj);
- }
- else
- {
- if (propertyNameList.Contains(pi.Name))
- {
- object obj = pi.GetValue(sourceArray[i], null);
- tempList.Add(obj);
- }
- }
- }
- object[] array = tempList.ToArray();
- result.LoadDataRow(array, true);
- }
- return result;
- }
四:ConvertDataViewToModel:
将Dataview中所以内容转成实体。
- /// <summary>
- /// 将视图转换成泛型集合
- /// </summary>
- /// <typeparam name="T">类型</typeparam>
- /// <param name="dataView">视图</param>
- /// <param name="model">泛型实例</param>
- /// <returns></returns>
- public static List<T> ConvertDataViewToModel<T>(DataView dataView, T model)
- where T:class
- {
- List<T> listReturn = new List<T>();
- Type modelType = model.GetType();
- DataTable dt = dataView.Table;
- //获取model所有类型
- PropertyInfo[] modelProperties = modelType.GetProperties();
- //遍历所有行,逐行添加对象
- for (int i = ; i < dt.Rows.Count; i++)
- {
- object obj = modelType.Assembly.CreateInstance(modelType.FullName);
- listReturn.Add((T)obj);
- //遍历model所有属性
- foreach (PropertyInfo pi in modelProperties)
- {
- //遍历所有列
- foreach (DataColumn col in dt.Columns)
- {
- //如果列数据类型与model的数据类型相同、名称相同
- if (col.DataType == pi.PropertyType
- && col.ColumnName == pi.Name)
- {
- pi.SetValue(obj, dt.Rows[i][col.ColumnName], null);
- }
- }
- }
- }
- return listReturn;
- }
UnitTest
这次的UntTest比较简单,覆盖率也不是100%,都快12点了,得休息了,就简单的弄了2个测试方法。如下:
- [TestMethod]
- public void TestConvertDataTableToModel()
- {
- DataTable dt = new DataTable();
- dt.Columns.Add("Id", typeof(string));
- dt.Columns.Add("Name", typeof(string));
- dt.Columns.Add("Address", typeof(string));
- dt.PrimaryKey = new DataColumn[] { dt.Columns[] };
- dt.Rows.Add("", "张三", "武汉市");
- dt.Rows.Add("", "李四", "北京市");
- dt.AcceptChanges();
- dt.Rows.Add("", "王五", "深圳市");
- List<People> allPeople = new List<People>();
- TransformUtil.ConvertDataTableToModel<People>(dt, allPeople);
- //断言是不是只有一个数据,平且是只是修改状态的王五这个人
- Assert.AreEqual(allPeople.Count, );
- Assert.AreEqual(allPeople[].Name, "王五");
- }
- [TestMethod]
- public void TestConvertModelToDataTable()
- {
- List<People> allPeople = new List<People>()
- {
- new People(){ Id="", Name="张三", Address ="武汉市"},
- new People(){ Id="", Name="李四", Address ="北京市"},
- new People(){ Id="", Name="王五", Address ="深圳市"}
- };
- DataTable dt = TransformUtil.ConvertModelToDataTable<People>(allPeople, null);
- //断言是不是有3行数据,数据的列有3列,第1列是不是Id,第一行第二列是不是张三
- Assert.AreEqual(dt.Rows.Count, );
- Assert.AreEqual(dt.Columns.Count, );
- Assert.AreEqual(dt.Columns[].ColumnName, "Id");
- Assert.AreEqual(dt.Rows[][], "张三");
- }
- }
测试结果如下:
两个测试用例均通过。
GitHub
本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。
文章是哥(mephisto)写的,SourceLink
多年前写的DataTable与实体类的转换,已放github的更多相关文章
- 多年前写的DataTable与实体类的转换
介绍 介绍 很多年前一直使用Ado.net,后来慢慢转型到其他的orm,在转型过程中,有意向将两者的模型结合起来,利用DataTable中的行状态完善一些mvc中的数据控制作用.现在把它放出来,留个纪 ...
- DataTable与实体类的转换
多年前写的DataTable与实体类的转换,已放github 阅读目录 介绍 起因 代码 UnitTest GitHub 介绍 很多年前一直使用Ado.net,后来慢慢转型到其他的orm,在转型过程中 ...
- DataTable与实体类互相转换
/// <summary> /// DataTable与实体类互相转换 /// </summary> /// <typeparam name="T"& ...
- 【转】DataTable与实体类互相转换
原文地址:https://www.cnblogs.com/marblemm/p/7084797.html /// <summary> /// DataTable与实体类互相转换 /// & ...
- DataTable转实体类
/// <summary> /// DataTable与实体类互相转换 /// </summary> /// <typeparam name="T"& ...
- DataTable和实体类通过反射相互转换
using System.Runtime.Serialization; using System.Data; using System.Reflection; using System.Collect ...
- .net 根据匿名类生成实体类,根据datatable生成实体类,根据sql生成实体类
在开发中可能会遇到这几种情况 1.EF或LINQ查询出来的匿名对象在其它地方调用不方便,又懒的手动建实体类 2.通过datatable反射实体需要先建一个类 ,头痛 3.通过SQL语句返回的实体也需要 ...
- 我写了一个java实体类,implements了Serializable接口,然后我如何让serialversionUID自动生成
写了一个java实体类,implements了Serializable接口,让serialversionUID自动生成方法: 1.点击类旁边的警告符号: 2.选择Add generated seria ...
- C# DataTable 转 实体类
C# 中查询结果DataTable转实体类: 比如:List<RtmInterview> rtmList = GetDataById( id); public List<RtmInt ...
随机推荐
- SNAT,是源地址转换,其作用是将ip数据包的源地址转换成另外一个地址
SNAT,可能有人觉得奇怪,好好的为什么要进行ip地址转换啊,为了弄懂这个问题,我们要看一下局域网用户上公网的原理,假设内网主机A(192.168.2.8)要和外网主机B(61.132.62.131) ...
- soap缓存问题
问题描述: ws提供方在原有基础上增加了一个方法,通过php的soap扩展硬是获取不到该方法,提示,该方法不存在. 问题跟节: soap缓存问题,导致无法获取最新的ws文件信息 解决办法: 1.直接在 ...
- Java集合源码分析(一)
Java集合工具包位于Java.util包下,包含了很多常用的数据结构,如数组.链表.栈.队列.集合.哈希表等.学习Java集合框架下大致可以分为如下五个部分:List列表.Set集合.Map映射.迭 ...
- Linux命令速查手册,超详细Linux命令教程
一.常用命令速查 ls cd pwd cat more less tail head cp scp mv mkdir rmdir touch rm ps kill top free clear tre ...
- jenkins 邮件配置
jenkins 自带一个邮件的通知的功能,但是自带的邮件通知功能,有点简单不能自定义信息,所以我们安装邮件插件Email-ext plugin.1.首先在系统管理-插件管理-安装Email-ext p ...
- Ionic 今天发布了Windows 桌面版的IDE Ionic Lab
Ionic简介: Ionic 是一个强大的 HTML5 应用程序开发框架,号称 Advanced HTML5 Hybrid Mobile AppFramework 是 AngularJS 移动端解决方 ...
- Mega Dropdown - 带子分类的响应式下拉菜单
当你在开发一个内容很多的 Web 项目的时候,最具挑战性的部分之一是为了如果更方便用户浏览这些内容.我们都能想到的一个例子是 Amazon,无限的类别以及它们的子类别.Mega Dropdown 是带 ...
- Scroll Depth – 衡量页面滚动的 Google 分析插件
Scroll Depth 是一个小型的 Google Analytics(谷歌分析)插件,可以让你衡量用户在页面上滚动了多远.它可以监控 25%.50%.75% 和 100% 四个滚动点,并发送谷歌分 ...
- CSS盒子模型
2016-10-22 <css入门经典>第6章 1.每个HTML元素对应于一个显示盒子,但不是所有的元素都显示在屏幕上. 2.HTML元素显示为CSS显示盒子的真正方法称为"可视 ...
- CSS常用样式(三)
一.2D变换 1.transform 设置或检索对象的转换 取值: none::以一个含六值的(a,b,c,d,e,f)变换矩阵的形式指定一个2D变换,相当于直接应用一个[a,b,c,d,e,f] ...