在程序中,往往会遇到一些小情况,就是数据库取出来的时候为了方便直接将数据通过存储在DataSet或DataTable中,这样做的一个后果是在日后的的对数据进行”细“操作时,就发现它可能没有List<T>那么方便,而另外一些时候(比如使用SqlBulkCopy的时候)使用DataTable会比较方便。于是我们就会想写一个专门的它们之间的互操作来使我们在操作它们的时候变得不那么复杂。网上关于它们之间的互操作的解决方法蛮多。这里参考了下它们,结合自己实际应用,写了一个它们之间互操,代码如下:

public static class DataTableEntityInteroperate
{
/// <summary>
/// List<T> to DataTable
/// </summary>
/// <typeparam name="T">Entity</typeparam>
/// <param name="entities">Entities</param>
/// <returns>DataTable</returns>
internal static DataTable ToDataTable<T>(this List<T> entities) where T : class,new()
{
//IsNull return
if (null == entities || entities.Count == )
return null;
//Initial Columns
DataTable dt = new DataTable();
PropertyInfo[] pArray = typeof(T).GetProperties();
try
{
Array.ForEach<PropertyInfo>(pArray, p =>
{
dt.Columns.Add(p.Name);
}); entities.ForEach(t =>
{
//Initial Rows
DataRow dr=dt.NewRow();
int i = ;
Array.ForEach<PropertyInfo>(pArray, p =>
{
if (dt.Columns.Contains(p.Name))
dr[i] = p.GetValue(t); //Assigned to each column
});
i++;
dt.Rows.Add(dr);//备忘,测试不仔细。
});
return dt;
}
catch (Exception)
{ throw;
} } /// <summary>
/// DataTable to Entities
/// </summary>
/// <typeparam name="T">Entity</typeparam>
/// <param name="dt">DataTable</param>
/// <returns>List<T</returns>
internal static List<T> ToEntities<T>(this DataTable dt)/*必须来在于数据库来自于文件可能存在问题*/ where T : class,new()
{
//IsNullable
if (null == dt || dt.Rows.Count == )
return null;
//Initial Entities
List<T> entities = new List<T>();
try
{
foreach (DataRow row in dt.Rows)
{
PropertyInfo[] pArray = typeof(T).GetProperties();
T entity = new T();
Array.ForEach<PropertyInfo>(pArray, p =>
{
if(row[p.Name]!=DBNull.Value)
p.SetValue(entity, row[p.Name], null);
});
entities.Add(entity);
}
return entities;
}
catch (Exception)
{
throw;
}
}
}

关乎ToEntities扩展方法的备注:这个方法适合的是DataTable是由数据库直接返回的情况。如果DataTable数据是由Xml文件直接反序列化而来。就要在初始化DataTable时候,对DaTable的列对应在数据实体中的类型进行指定。

关于DataTable数据是直接从文件而来的备注:

public class XmlHelper
{
/// <summary> /// 将XML转换为DATATABLE /// </summary> /// <param name="FileURL"></param> /// <returns></returns> public static DataTable XmlAnalysisArray(string filepath)
{ try
{ DataSet ds = new DataSet(); ds.ReadXml(filepath); return ds.Tables[]; } catch (Exception ex)
{ throw ex; } } /// <summary> /// 将DATASET 转换为 XML /// </summary> /// <param name="FileURL"></param> /// <returns></returns> public static void DatasetConversionXML(DataSet ds, string FileURL)
{ try
{
ds.WriteXml(FileURL); } catch (Exception ex)
{ throw ex;
}
} /// <summary>
/// Xml序列化
/// </summary>
/// <typeparam name="T">对象的类型</typeparam>
/// <param name="t">序列化对象实例</param>
/// <param name="filePath">文件路径</param>
public static void XmlSerializer<T>(List<T> t, string filePath)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<T>));
StreamWriter writer = new StreamWriter(filePath);
//将s对象写入到指定的IO流文件中
try
{
xmlSerializer.Serialize(writer, t);
}
catch (Exception)
{ //errr message
}
finally
{
writer.Close();
}
} /// <summary>
/// Xml反序列化
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="t">对象实例</param>
public static List<T> XmlDeserialize<T>(List<T> t, string filePath) //必须是经过同样的过程反序列化好的文件
{
XmlSerializer mySerializer = new XmlSerializer(typeof(List<T>));
FileStream myFileStream = null;
if (File.Exists(filePath)) //检查文件是否存在
{
try
{
myFileStream = new FileStream(filePath, FileMode.Open);
t = (List<T>)mySerializer.Deserialize(myFileStream);
}
catch (FileNotFoundException)
{
//File not Found
}
catch (Exception)
{
//the other error message
}
finally
{
myFileStream.Close(); }
}
return t;
} }

Xml文件是直接从DataTable序列化而成,而不是由List<T>序列化而来。

做如下调用则会抛出异常(异常处理已经加上,谢谢Mainz)

 var dt = XmlHelper.XmlAnalysisArray(Server.MapPath(@"XML\Students"));
var list= dt.ToEntities<Student>();

调试会发现。StudentID在实体中是Int32类型。而反序列化出来的是String类型。关于此处的完美解决方案,希望大家能够指点。此处美中不足。

代码下载

反射小应用之DataTable和List<T>互操作的更多相关文章

  1. 反射类属性生成DataTable

    public class People //类名 { private static string name; //字段 private string sex;//字段 public string Se ...

  2. 【小知识】DataTable 转 List -----------点滴之水,汇涓涓细流,成汪洋大海

    在大部分时候我们从ADO中得到的数据都是DataTable.DataSet数据源,然而有强迫症的同学老是喜欢折腾,硬是要把它转换为实体集合,说是DataTable效率差云云,于是乎收到了同化. 必要信 ...

  3. c# 反射小Demo

    今天看了一下C#的反射,之前一直感觉反射是一种很高大上的东东,现在才发现不过是纸老虎而以. 所谓的反射就是,只是知道一个它是一个对象不知道其中有什么字段方法属性等,而反射就是用来获取一个未知对象的字段 ...

  4. 反射List<M> To DataTable|反射IList To DataTable|反射 DataTable To List<M>

    将DataTable集合反射获取 List<M> /// <summary> /// 根据DataTable集合反射获取 List<M> /// </summ ...

  5. 用反射写自己的DataTable转为对应的Mod

    之前写过类似的方法,今天做项目的时候又遇到了,以前的代码没有保存,导致又得重新写 场景:当我们定义自己的很多模型(Mods)的时候,而数据库读取出来的却是DataSet,DataTable类型的时候, ...

  6. java反射小实例

    利用反射实现 对配置文件的更改达到更改方法的目的 文件夹目录 首先Student类中有个sleep方法 pro.properties定义了参数 最后是RelectTestMain. package c ...

  7. java反射小例子

    package com.txwsqk.reflect; public class Car { private String brand; private String color; private i ...

  8. 使用JavaScriptSerializer序列化集合、字典、数组、DataTable为JSON字符串 分类: 前端 数据格式 JSON 2014-10-30 14:08 169人阅读 评论(0) 收藏

    一.JSON简介 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式. JSON是"名值对"的集合.结构由大 ...

  9. Python:Day25 成员修饰符、特殊成员、反射、单例

    一.成员修饰符 共有成员 私有成员,__字段名,__方法 - 无法直接访问,只能间接访问 class Foo: def __init__(self,name,age): self.name = nam ...

随机推荐

  1. Matlab实现求a到b被c整除的个数

    我先想到的是for循环........ 然后sum(find(mod(a:b,c)==0)),从10到100得到874,为什么不对呢? 比如a = [1 2 3 4  2 3 4 2],find(a= ...

  2. js 判断是否为chrome浏览器

    var isChrome =navigator.userAgent.indexOf("Chrome") !== -1 用 navigator.appVersion 不好使,因为al ...

  3. 一些linux的问题

    本文罗列的是我在学习linux与shell编程时所遇到的一些问题.我相信既然存在问题那么就会有需求,记录于此,希望可以快速帮助到大家. 1.在vim中用“/word"查找后,vim会以棕色背 ...

  4. Block、委托、回调函数原理剖析(在Object C语境)——这样讲还不懂,根本不可能!

    开篇:要想理解Block和委托,最快的方法是搞明白“回调函数”这个概念. 做为初级选手,我们把Block.委托.回调函数,视为同一原理的三种不同名称.也就是说,现在,我们把这三个名词当成一回事.在这篇 ...

  5. Genymotion加载so出错解决方案

    通过网上所搜得出结论: Genymotion是x86的架构,而我们的so库是arm架构的 解决:安装Genymotion-ARM-Translation.zip 1.下载:http://pan.bai ...

  6. application.xml定时

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  7. float和decimal执行效率 (只是代码 没有分析—)

    float版: public static void getSmallFramPoint() { string framString ="Row,"+"Colum,&qu ...

  8. NSDate & NSDateFormatter

    #import <Foundation/Foundation.h>   int main(int argc, const char * argv[]) {    @autoreleasep ...

  9. c语言头文件和源文件不在同一个目录

    http://www.cnblogs.com/ShaneZhang/archive/2013/05/20/3088688.html 从工程上讲,头文件的文件名应该与对应的源文件名相同便于维护,如果头文 ...

  10. Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.

    在部署的时候出现Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server ...