DataTable 和List之间相互转换的方法

  • Post author:
  • Post category:其他


一、List<T>/IEnumerable转换到DataTable/DataView


方法一:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59


/// <summary>


/// Convert a List{T} to a DataTable.


/// </summary>


private


DataTable ToDataTable<T>(List<T> items)


{




var


tb =


new


DataTable(


typeof


(T).Name);




PropertyInfo[] props =


typeof


(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);




foreach


(PropertyInfo prop


in


props)




{




Type t = GetCoreType(prop.PropertyType);




tb.Columns.Add(prop.Name, t);




}




foreach


(T item


in


items)




{




var


values =


new


object


[props.Length];




for


(


int


i = 0; i < props.Length; i++)




{




values[i] = props[i].GetValue(item,


null


);




}




tb.Rows.Add(values);




}




return


tb;


}


/// <summary>


/// Determine of specified type is nullable


/// </summary>


public


static


bool


IsNullable(Type t)


{




return


!t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() ==


typeof


(Nullable<>));


}


/// <summary>


/// Return underlying type if type is Nullable otherwise return the type


/// </summary>


public


static


Type GetCoreType(Type t)


{




if


(t !=


null


&& IsNullable(t))




{




if


(!t.IsValueType)




{




return


t;




}




else




{




return


Nullable.GetUnderlyingType(t);




}




}




else




{




return


t;




}


}


方法二:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21


public


static


DataTable ToDataTable<T>(IEnumerable<T> collection)




{




var


props =


typeof


(T).GetProperties();




var


dt =


new


DataTable();




dt.Columns.AddRange(props.Select(p =>


new


DataColumn(p.Name, p.PropertyType)).ToArray());




if


(collection.Count() > 0)




{




for


(


int


i = 0; i < collection.Count(); i++)




{




ArrayList tempList =


new


ArrayList();




foreach


(PropertyInfo pi


in


props)




{




object


obj = pi.GetValue(collection.ElementAt(i),


null


);




tempList.Add(obj);




}




object


[] array = tempList.ToArray();




dt.LoadDataRow(array,


true


);




}




}




return


dt;




}


二、DataTable转换到List


方法一:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59


public


static


IList<T> ConvertTo<T>(DataTable table)


{




if


(table ==


null


)




{




return


null


;




}




List<DataRow> rows =


new


List<DataRow>();




foreach


(DataRow row


in


table.Rows)




{




rows.Add(row);




}




return


ConvertTo<T>(rows);


}


public


static


IList<T> ConvertTo<T>(IList<DataRow> rows)


{




IList<T> list =


null


;




if


(rows !=


null


)




{




list =


new


List<T>();




foreach


(DataRow row


in


rows)




{




T item = CreateItem<T>(row);




list.Add(item);




}




}




return


list;


}


public


static


T CreateItem<T>(DataRow row)


{




T obj =


default


(T);




if


(row !=


null


)




{




obj = Activator.CreateInstance<T>();




foreach


(DataColumn column


in


row.Table.Columns)




{




PropertyInfo prop = obj.GetType().GetProperty(column.ColumnName);




try




{




object


value = row[column.ColumnName];




prop.SetValue(obj, value,


null


);




}




catch




{


//You can log something here




//throw;




}




}




}


return


obj;


}


方法二:

把查询结果以DataTable返回很方便,但是在检索数据时又很麻烦,没有模型类型检索方便。

所以很多人都是按照以下方式做的:

1

2

3

4


// 获得查询结果


DataTable dt = DbHelper.ExecuteDataTable(...);


// 把DataTable转换为IList<UserInfo>


IList<UserInfo> users = ConvertToUserInfo(dt);

问题:如果此系统有几十上百个模型,那不是每个模型中都要写个把DataTable转换为此模型的方法吗?

解决:能不能写个通用类,可以把DataTable转换为任何模型,呵呵,这就需要利用反射和泛型了

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46


using


System;


using


System.Collections.Generic;


using


System.Text;


using


System.Data;


using


System.Reflection;


namespace


NCL.Data


{




/// <summary>




/// 实体转换辅助类




/// </summary>




public


class


ModelConvertHelper<T>


where


T :


new


()




{




public


static


IList<T> ConvertToModel(DataTable dt)




{




// 定义集合




IList<T> ts =


new


List<T>();





// 获得此模型的类型




Type type =


typeof


(T);




string


tempName =


""


;





foreach


(DataRow dr


in


dt.Rows)




{




T t =


new


T();




// 获得此模型的公共属性




PropertyInfo[] propertys = t.GetType().GetProperties();




foreach


(PropertyInfo pi


in


propertys)




{




tempName = pi.Name;


// 检查DataTable是否包含此列





if


(dt.Columns.Contains(tempName))




{




// 判断此属性是否有Setter




if


(!pi.CanWrite)


continue


;





object


value = dr[tempName];




if


(value != DBNull.Value)




pi.SetValue(t, value,


null


);




}




}




ts.Add(t);




}




return


ts;




}




}


}

使用方式:

1

2

3

4


// 获得查询结果


DataTable dt = DbHelper.ExecuteDataTable(...);


// 把DataTable转换为IList<UserInfo>


IList<UserInfo> users = ModelConvertHelper<UserInfo>.ConvertToModel(dt);

原文地址:

https://www.cnblogs.com/shiyh/p/7478241.html


将DataTable转换为List<T>对象遇到问题:类型“System.Int64”的对象无法转换为类型“System.Int32”



2017年09月03日 15:26:45



阅读数:1028





前言:



用三层开发的时候,D层经常会用到把DataTable对象转换为List对象的问题,一般情况下我们都会用到一个TableToList()方法,之前都是照着网上敲得,完了大致看一下就开始用了,也没出什么问题,也就没有仔细研究,这次用这个方法转换的时候遇到了一个异常(如题),出来混迟早要还的,这次让我重新研究了一下这个方法。





方法思路:



简单了解一下TableToList()方法的思路。

1. 初始化一个List对象,获取到T所有的属性,

2. 初始化一个T对象 遍历所有属性,

3. 如果DataTable中含有相应属性的值则为T对象赋值,如果没有对应的列则检查数据模型是否定义有误(属性名与列名比较时不区分大小写)

4. 将T对象添加到List对象中





遇到的问题


这里写图片描述

我也是很奇怪,我的plan_flag字段在前边明明传进去的就是int32的,到这里怎么成了int64不能转换成int32位了。

根据之前的思路和异常出现的地方,问题出在给对象的属性赋值这步。

因为转换时在DataTable里某个字段类型是Int32会有问题,报异常,所以我们可在赋值的时候加一个判断:

//加一重if判断,如果属性值是int32类型的,就进行一次强制转换
if(pi.GetMethod.ReturnParameter.ParameterType.Name == "Int32")
{
value = Convert.ToInt32(value);
}
pi.SetValue(t, value, null);





完整的方法


/// <summary>
    /// DataTable转换为List
    /// </summary>
    /// <typeparam name="T">实体对象</typeparam>
    /// <param name="dt">datatable表</param>
    /// <returns>返回list集合</returns>

        public List<T> TableToList<T>(DataTable dt) where T : new()
        {
            //定义集合
            List<T> list = new List<T>();
            //获得此模型的类型
            Type type = typeof(T);
            //定义一个临时变量
            string tempName = string.Empty;
            //遍历Datatable中所有的数据行
            foreach (DataRow dr in dt.Rows)
            {
                T t = new T();
                //获得此模型的公共属性
                PropertyInfo[] propertys = t.GetType().GetProperties();
                //遍历该对象的所有属性
                foreach (PropertyInfo pi in propertys)
                {
                    //将属性名称赋值给临时变量
                    tempName = pi.Name;
                    //检查DataTable是否包含此列(列名==对象的属性名)
                    if (dt.Columns.Contains(tempName))
                    {
                        //判断此属性是否有Setter
                        if (!pi.CanWrite) continue;//该属性不可写,直接跳出
                        //取值
                        object value = dr[tempName];
                        //如果非空,则赋给对象的属性
                        if (value != DBNull.Value)
                        {
                         //加一重if判断,如果属性值是int32类型的,就进行一次强制转换
                           if(pi.GetMethod.ReturnParameter .ParameterType.Name=="Int32")
                            {
                                value = Convert.ToInt32(value);
                            }
                            pi.SetValue(t, value, null);
                        }

                    }
                }
                //对象添加到泛型集合中
                list.Add(t);
            }
            return list;
        }





总结



还是多一点了解比较好,知其然也要之前所以然,要不然出问题的时候找不到问题原因,更找不到解决方法。