using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text; namespace TransformDTToModel
{
public class TransformUtil
{
/// <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);
} /// <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;
} /// <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;
} /// <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;
} }
}

TransformUtil

  public class People
{
public string Id { get; set; } public string Name { get; set; } public string Address { get; set; }
}

单元测试

[TestClass]
public class UnitTestForTransformDTAndModel
{
[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[0] }; dt.Rows.Add("0001", "张三", "武汉市");
dt.Rows.Add("0002", "李四", "北京市");
dt.AcceptChanges();
dt.Rows.Add("0003", "王五", "深圳市"); List<People> allPeople = new List<People>(); TransformUtil.ConvertDataTableToModel<People>(dt, allPeople); //断言是不是只有一个数据,平且是只是修改状态的王五这个人
Assert.AreEqual(allPeople.Count, 1);
Assert.AreEqual(allPeople[0].Name, "王五");
} [TestMethod]
public void TestConvertModelToDataTable()
{
List<People> allPeople = new List<People>()
{
new People(){ Id="0001", Name="张三", Address ="武汉市"},
new People(){ Id="0002", Name="李四", Address ="北京市"},
new People(){ Id="0003", Name="王五", Address ="深圳市"}
}; DataTable dt = TransformUtil.ConvertModelToDataTable<People>(allPeople, null); //断言是不是有3行数据,数据的列有3列,第1列是不是Id,第一行第二列是不是张三
Assert.AreEqual(dt.Rows.Count, 3);
Assert.AreEqual(dt.Columns.Count, 3);
Assert.AreEqual(dt.Columns[0].ColumnName, "Id");
Assert.AreEqual(dt.Rows[0][1], "张三");
}
}

DataTable转换为实体集合的更多相关文章

  1. 再谈使用Emit把Datatable转换为对象集合(List<T>)

    一.前因和存在的问题 前面我写了一篇<使用Emit把Datatable转换为对象集合(List<T>)>的博文,其实起源于我自己编写的一个orm工具(见前面几篇博文有介绍),里 ...

  2. 使用Emit把Datatable转换为对象集合(List<T>)

    Emit生成动态方法部分摘自网上,但是经过修改,加入了对委托的缓存以及类结构的调整,使之调用更简洁方便.大致的思路是:要实现转换datatable到某个指定对象的集合,本质是实现转换一个datarow ...

  3. C#中DataTable与实体集合通用转换(使用扩展方法)

    本案例提供了:把DataRow转换为单个实体.dataTable转换为List泛型支持时间格式转换. 下文的方法都是扩展方法.扩展方法要求写在静态类中,方法也要静态. 它必须在一个非嵌套.非泛型的静态 ...

  4. 三层架构中bll层把datatable转换为实体model的理解

    看了很多人的项目,很多都是用到三层架构,其中BLL层中有一种将DataTable转换为实体的方法.一直没有明白为啥要这样做,今天特意去搜索了一下,如果没有答案我是准备提问,寻求解答了.还好找到一个相关 ...

  5. 通过表达式树把datareader和datatable转换为实体

    续上两篇文章,使用emit构造dynamic method,把 datareader转换为实体,以避免直接使用反射来实现带来的性能损失.代码看似没有纰漏,但是实际上我在framwork4下运行时,调用 ...

  6. 反射 DataTable拓展方法 转实体对象、实体集合、JSON

    Mapper类 using System; using System.Collections.Generic; using System.Data; using System.Globalizatio ...

  7. DataTable数据转换为实体

    我们在用三层架构编写软件时,常常会遇到例如以下问题,就是三层之间的參数传递问题:假设我们在D层查询出数据是DataTable类型的,那么我们在B层甚至U层使用这条数据时,就要用DataTable类型来 ...

  8. 自用的基于Emit的C#下DataTable转实体类方法

    之前一直在做WebForm的开发,数据绑定时直接DataTable绑定Gridview很方便,但是最近开始往MVC转,数据列表的传递和页面展示基本上是以List为主,像下面这样,遍历实体类的各个字段去 ...

  9. [工具类]DataTable与泛型集合List互转

    写在前面 工作中经常遇到datatable与list,对于datatable而言操作起来不太方便.所以有的时候还是非常希望通过泛型集合来进行操作的.所以这里就封装了一个扩展类.也方便使用. 类 方法中 ...

随机推荐

  1. POJ:3292-Semi-prime H-numbers(艾氏筛选法拓展)

    Semi-prime H-numbers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10466 Accepted: 4665 ...

  2. [Bzoj4289]PA2012 Tax(Dijkstra+技巧建图)

    Description 给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边 ...

  3. ajax跨域请求_url:http://XXX

    利用别的项目提供的一个接口,传入用户名和密码,根据返回的结果判断登陆成功与否. 不经过后台,在js中用ajax实现.对ajax而言,发送跨域请求,与一般写法不同. 如果支持jsonp,则将dataTy ...

  4. 安装完最小化 RHEL/CentOS 7 后需要做的 30 件事情(一)

    本文导航 -1. 注册并启用红帽订阅 -2. 使用静态 IP 地址配置网络 -3. 设置服务器的主机名称 -4. 更新或升级最小化安装的 CentOS -5. 安装命令行 Web 浏览器 -6. 安装 ...

  5. MyEclipse - 问题集 - maven update project 后,项目jdk的版本变化

    解决方法: 进入maven安装根目录,conf/settings.xml <profiles> <profile> <id>jdk-1.7</id> & ...

  6. c#集合的使用

    //添加单个元素用Add方法 ArrayList list = new ArrayList(); list.Add(true); list.Add(); list.Add("小陈" ...

  7. C语言库函数实现 【微软面试100题 第八十三题】

    题目要求 1.strcpy/memcpy/memmove: 2.memset函数: 3.字符串处理函数. 题目分析 1.接口定义: char * strcpy(char * dest, const c ...

  8. USACO Section2.3 Longest Prefix 解题报告 【icedream61】

    prefix解题报告------------------------------------------------------------------------------------------ ...

  9. visio2013密钥

    66DNF-28W69-W4PPV-W3VYT-TJDBQ http://www.xiazaizhijia.com/rjjc/133264.html

  10. BETA0

    目录 过去存在的问题 任务分工 规范 后端总结 卉卉 家灿 前端总结 绪佩 青元 恺琳 宇恒 丹丹 算法&API接口 家伟 鸿杰 一好 文档&博客撰写 政演 产品功能 我们已经坐了哪些 ...