DataTabel转换List时GetProperty反射赋值报错:从“System.String”到“System.Nullable[[System.DateTime]的强制转换无效

在写代码时经常会碰见可空类型的数据段,Table转换List和List转Table时会很头疼,现在记录下解决方案。

DataTable转换为List

下方代码适合所有可空类型的转换——TableToList:

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 List<T> TableToEntity<T>(DataTable dt) where T : class, new()
{
// 定义集合
List<T> ts = new List<T>();

if (dt != null && dt.Rows.Count > 0)
{
// 获得此模型的类型
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);
// pi.SetValue(t, Convert.ChangeType(value, pi.PropertyType, CultureInfo.CurrentCulture), null);
pi.SetValue(t, ChanageType(value,pi.PropertyType), null);
}
}
}
ts.Add(t);
}
}

return ts;
}
//转换可空类型 如:DateTime?
private static object ChanageType(object value, Type convertsionType)
{
//判断convertsionType类型是否为泛型,因为nullable是泛型类,
if (convertsionType.IsGenericType &&
//判断convertsionType是否为nullable泛型类
convertsionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
if (value == null || value.ToString().Length == 0)
{
return null;
}

//如果convertsionType为nullable类,声明一个NullableConverter类,该类提供从Nullable类到基础基元类型的转换
NullableConverter nullableConverter = new NullableConverter(convertsionType);
//将convertsionType转换为nullable对的基础基元类型
convertsionType = nullableConverter.UnderlyingType;
}
return Convert.ChangeType(value, convertsionType);
}

List转换为DataTable

下方代码为List转Table:

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
/// <summary>  
/// 转化一个DataTable
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public static DataTable ToDataTable<T>(IEnumerable<T> list)
{
//创建属性的集合
List<PropertyInfo> pList = new List<PropertyInfo>();
//获得反射的入口
Type type = typeof(T);
DataTable dt = new DataTable();
//把所有的public属性加入到集合 并添加DataTable的列
Array.ForEach<PropertyInfo>(type.GetProperties(), p => { pList.Add(p); dt.Columns.Add(p.Name, p.PropertyType); });
foreach (var item in list)
{
//创建一个DataRow实例
DataRow row = dt.NewRow();
//给row 赋值
pList.ForEach(p => row[p.Name] = p.GetValue(item, null));
//加入到DataTable
dt.Rows.Add(row);
}
return dt;
}

但是如果实体类有可空类型的又会报错:System.NotSupportedException: DataSet 不支持 System.Nullable<>

解决方法:

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
public static DataTable ToDataTable<T>(IEnumerable<T> list)
{
try
{
DataTable dtReturn = new DataTable();
// column names
PropertyInfo[] oProps = null;
// Could add a check to verify that there is an element 0
foreach (T rec in list)
{
// Use reflection to get property names, to create table, Only first time, others will follow
if (oProps == null)
{
oProps = ((Type)rec.GetType()).GetProperties();
foreach (PropertyInfo pi in oProps)
{
Type colType = pi.PropertyType; if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
}
}
DataRow dr = dtReturn.NewRow(); foreach (PropertyInfo pi in oProps)
{
dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue(rec, null);
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
catch(Exception es)
{
throw es;
}

}

DataTabel转换List时GetProperty反射赋值报错:从“System.String”到“System.Nullable[[System.DateTime]的强制转换无效

https://ganzhixiong.com/p/ee63ef96/

Author

干志雄

Posted on

2021-06-24

Updated on

2021-06-24

Licensed under

Comments