将 DataTable 转换为 List<T>
Posted
技术标签:
【中文标题】将 DataTable 转换为 List<T>【英文标题】:Convert DataTable to List<T> 【发布时间】:2010-11-28 11:42:56 【问题描述】:我有一个MyType
类型的强类型数据表,我想将其转换为List<MyType>
。
我该怎么做?
谢谢。
【问题讨论】:
DataTable转Dictionary的场景可能比List多。 DataTable 有行和列。 Dictionary 比 List 更能代表这种结构。 或者字典列表。您能否提供有关您正在尝试做的事情的更多信息? @Kris-I:什么清单? @Vadim - 仅当表中有唯一键并且您将通过该键查找值时,字典才适用。否则,这是您不需要的开销。合适的时候你可以使用 Linq.ToDictionary
方法
【参考方案1】:
以下内容在一行中完成:
dataTable.Rows.OfType<DataRow>()
.Select(dr => dr.Field<MyType>(columnName)).ToList();
[编辑:如果无法编译,请将System.Data.DataSetExtensions
的引用添加到您的项目中]
【讨论】:
这里的 columnName 值是多少? @CodeMan03columnName
的值是具有MyType
的任何列的名称。另一方面,如果每一行都有多个列,每列代表MyType
的一个属性,那么理查德的答案是正确的。【参考方案2】:
List<MyType> listName = dataTableName.AsEnumerable().Select(m => new MyType()
ID = m.Field<string>("ID"),
Description = m.Field<string>("Description"),
Balance = m.Field<double>("Balance"),
).ToList()
【讨论】:
MyType 是一个对象,您将在上面显示的代码之前创建一个具有相同变量(ID、描述、余额)的对象【参考方案3】:DataTable 有 Linq 扩展方法。
添加引用:System.Data.DataSetExtensions.dll
然后包含命名空间:using System.Data.DataSetExtensions
最后你可以在 DataSet 和 DataTables 上使用 Linq 扩展:
var matches = myDataSet.Tables.First().Where(dr=>dr.Field<int>("id") == 1);
在 .Net 2.0 上,您仍然可以添加泛型方法:
public static List<T> ConvertRowsToList<T>( DataTable input, Convert<DataRow, T> conversion)
List<T> retval = new List<T>()
foreach(DataRow dr in input.Rows)
retval.Add( conversion(dr) );
return retval;
【讨论】:
如果卡在 .NET 2.0 有没有简单的方法? +1 亲爱的!但是这里的Convert
关键字是什么?你的意思是Converter
?
@Keith - 它必须是 Convert er what is the Convert keyword here? Do you mean Converter?
实际上他的意思是传递一个 func<DataRow, T> conversion
,这是任何 delegate/function
期望一个 datarow
并且它的输出将是一个 T
实体。 .
@auujay - 您可以使用.net 2.0
轻松做到这一点.. 这是链接.. http://codenicely.blogspot.in/2012/02/converting-your-datatable-into-list.html
【参考方案4】:
数据表到列表
#region "getobject filled object with property reconized"
public List<T> ConvertTo<T>(DataTable datatable) where T : new()
List<T> Temp = new List<T>();
try
List<string> columnsNames = new List<string>();
foreach (DataColumn DataColumn in datatable.Columns)
columnsNames.Add(DataColumn.ColumnName);
Temp = datatable.AsEnumerable().ToList().ConvertAll<T>(row => getObject<T>(row, columnsNames));
return Temp;
catch
return Temp;
public T getObject<T>(DataRow row, List<string> columnsName) where T : new()
T obj = new T();
try
string columnname = "";
string value = "";
PropertyInfo[] Properties;
Properties = typeof(T).GetProperties();
foreach (PropertyInfo objProperty in Properties)
columnname = columnsName.Find(name => name.ToLower() == objProperty.Name.ToLower());
if (!string.IsNullOrEmpty(columnname))
value = row[columnname].ToString();
if (!string.IsNullOrEmpty(value))
if (Nullable.GetUnderlyingType(objProperty.PropertyType) != null)
value = row[columnname].ToString().Replace("$", "").Replace(",", "");
objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(Nullable.GetUnderlyingType(objProperty.PropertyType).ToString())), null);
else
value = row[columnname].ToString().Replace("%", "");
objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(objProperty.PropertyType.ToString())), null);
return obj;
catch
return obj;
#endregion
IEnumerable 集合到数据表
#region "New DataTable"
public DataTable ToDataTable<T>(IEnumerable<T> collection)
DataTable newDataTable = new DataTable();
Type impliedType = typeof(T);
PropertyInfo[] _propInfo = impliedType.GetProperties();
foreach (PropertyInfo pi in _propInfo)
newDataTable.Columns.Add(pi.Name, pi.PropertyType);
foreach (T item in collection)
DataRow newDataRow = newDataTable.NewRow();
newDataRow.BeginEdit();
foreach (PropertyInfo pi in _propInfo)
newDataRow[pi.Name] = pi.GetValue(item, null);
newDataRow.EndEdit();
newDataTable.Rows.Add(newDataRow);
return newDataTable;
【讨论】:
看起来不错,但如何调用该方法? 这是一段很棒的代码!!!它完全符合我的需要。有些年头,但仍然非常有用。谢谢。 如何调用 ConvertTo 方法?【参考方案5】:下面发布的使用反射的方法 ConvertToList 非常适合我。谢谢。
我做了一些修改,使其适用于 T 属性类型的转换。
public List<T> ConvertToList<T>(DataTable dt)
var columnNames = dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.ToList();
var properties = typeof(T).GetProperties();
return dt.AsEnumerable().Select(row =>
var objT = Activator.CreateInstance<T>();
foreach (var pro in properties)
if (columnNames.Contains(pro.Name))
PropertyInfo pI = objT.GetType().GetProperty(pro.Name);
pro.SetValue(objT, row[pro.Name] == DBNull.Value ? null : Convert.ChangeType(row[pro.Name], pI.PropertyType));
return objT;
).ToList();
希望对您有所帮助。 问候。
【讨论】:
这个的好处是它不关心您的类型是否具有在数据表中没有匹配列的属性。谢谢。【参考方案6】:IEnumerable<DataRow> rows = dataTable.AsEnumerable();
(System.Data.DataSetExtensions.dll)
IEnumerable<DataRow> rows = dataTable.Rows.OfType<DataRow>();
(System.Core.dll)
【讨论】:
【参考方案7】:这很好用!!
我根据@suneelsarraf 的回答做了一些更新,我删除了Convert.ChangeType()
,因为它一直在抛出Invalid Cast Exception
。来看看吧!
#region *** Convert DT to List<Object> ***
private List<I> ConvertTo<I>(DataTable datatable) where I : class
List<I> lstRecord = new List<I>();
try
List<string> columnsNames = new List<string>();
foreach (DataColumn DataColumn in datatable.Columns)
columnsNames.Add(DataColumn.ColumnName);
lstRecord = datatable.AsEnumerable().ToList().ConvertAll<I>(row => GetObject<I>(row, columnsNames));
return lstRecord;
catch
return lstRecord;
private I GetObject<I>(DataRow row, List<string> columnsName) where I : class
I obj = (I)Activator.CreateInstance(typeof(I));
try
PropertyInfo[] Properties = typeof(I).GetProperties();
foreach (PropertyInfo objProperty in Properties)
string columnname = columnsName.Find(name => name.ToLower() == objProperty.Name.ToLower());
if (!string.IsNullOrEmpty(columnname))
object dbValue = row[columnname];
if (dbValue != DBNull.Value)
if (Nullable.GetUnderlyingType(objProperty.PropertyType) != null)
objProperty.SetValue(obj, Convert.ChangeType(dbValue, Type.GetType(Nullable.GetUnderlyingType(objProperty.PropertyType).ToString())), null);
else
objProperty.SetValue(obj, Convert.ChangeType(dbValue, Type.GetType(objProperty.PropertyType.ToString())), null);
return obj;
catch(Exception ex)
return obj;
#endregion
这就是你在代码中使用的方式。
// Other Codes Here
var lstResult = ConvertTo<TEntity>(dataTableName); // Convert DT to List<TEntity>
玩得开心!在 2020 年保持安全。
【讨论】:
太棒了。用作 DataTable 的扩展,并在我第一次运行时工作。【参考方案8】:通过使用AsEnumerable
调用扩展datatable
,创建一个类型为<DataRow>
的列表。
var mylist = dt.AsEnumerable().ToList();
干杯!!快乐编码
【讨论】:
DataTable 没有 AsEnumerable 方法,除非您的解决方案需要参考和使用才能工作。 这个解决方案究竟在哪里将数据表转换为 Object假设你的DataRow
s 继承自你自己的类型,比如MyDataRowType
,这应该可以工作:
List<MyDataRowType> list = new List<MyDataRowType>();
foreach(DataRow row in dataTable.Rows)
list.Add((MyDataRowType)row);
正如您在评论中所说,这是假设您使用的是 .NET 2.0 并且无权访问 LINQ 扩展方法。
【讨论】:
为什么不做一个列表请试试这个代码:
public List<T> ConvertToList<T>(DataTable dt)
var columnNames = dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.ToList();
var properties = typeof(T).GetProperties();
return dt.AsEnumerable().Select(row =>
var objT = Activator.CreateInstance<T>();
foreach (var pro in properties)
if (columnNames.Contains(pro.Name))
pro.SetValue(objT, row[pro.Name]);
return objT;
).ToList();
【讨论】:
我发现您的示例很有用,但是它不适用于可为空的属性,因此我更改了将值设置为pro.SetValue(objT, row[pro.Name] == DBNull.Value ? default(T) : row[pro.Name]);
的行【参考方案11】:
感谢所有帖子.... 我已经使用 Linq Query 完成了,要查看此内容,请访问以下链接
http://codenicely.blogspot.com/2012/02/converting-your-datatable-into-list.html
【讨论】:
【参考方案12】:试试这段代码,这是将数据表转换为列表的最简单方法
List<DataRow> listtablename = dataTablename.AsEnumerable().ToList();
【讨论】:
我收到此错误; “System.Data.EnumerableRowCollection有一点example可以用
DataTable dt = GetCustomersDataTable(null);
IEnumerable<SelectListItem> lstCustomer = dt.AsEnumerable().Select(x => new SelectListItem()
Value = x.Field<string>("CustomerId"),
Text = x.Field<string>("CustomerDescription")
).ToList();
return lstCustomer;
【讨论】:
【参考方案14】:您可以将数据表转换为列表。检查以下链接
https://***.com/a/35171050/1805776
public static class Helper
public static List<T> DataTableToList<T>(this DataTable dataTable) where T : new()
var dataList = new List<T>();
//Define what attributes to be read from the class
const System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance;
//Read Attribute Names and Types
var objFieldNames = typeof(T).GetProperties(flags).Cast<System.Reflection.PropertyInfo>().
Select(item => new
Name = item.Name,
Type = Nullable.GetUnderlyingType(item.PropertyType) ?? item.PropertyType
).ToList();
//Read Datatable column names and types
var dtlFieldNames = dataTable.Columns.Cast<DataColumn>().
Select(item => new
Name = item.ColumnName,
Type = item.DataType
).ToList();
foreach (DataRow dataRow in dataTable.AsEnumerable().ToList())
var classObj = new T();
foreach (var dtField in dtlFieldNames)
System.Reflection.PropertyInfo propertyInfos = classObj.GetType().GetProperty(dtField.Name);
var field = objFieldNames.Find(x => x.Name == dtField.Name);
if (field != null)
if (propertyInfos.PropertyType == typeof(DateTime))
propertyInfos.SetValue
(classObj, convertToDateTime(dataRow[dtField.Name]), null);
else if (propertyInfos.PropertyType == typeof(Nullable<DateTime>))
propertyInfos.SetValue
(classObj, convertToDateTime(dataRow[dtField.Name]), null);
else if (propertyInfos.PropertyType == typeof(int))
propertyInfos.SetValue
(classObj, ConvertToInt(dataRow[dtField.Name]), null);
else if (propertyInfos.PropertyType == typeof(long))
propertyInfos.SetValue
(classObj, ConvertToLong(dataRow[dtField.Name]), null);
else if (propertyInfos.PropertyType == typeof(decimal))
propertyInfos.SetValue
(classObj, ConvertToDecimal(dataRow[dtField.Name]), null);
else if (propertyInfos.PropertyType == typeof(String))
if (dataRow[dtField.Name].GetType() == typeof(DateTime))
propertyInfos.SetValue
(classObj, ConvertToDateString(dataRow[dtField.Name]), null);
else
propertyInfos.SetValue
(classObj, ConvertToString(dataRow[dtField.Name]), null);
else
propertyInfos.SetValue
(classObj, Convert.ChangeType(dataRow[dtField.Name], propertyInfos.PropertyType), null);
dataList.Add(classObj);
return dataList;
private static string ConvertToDateString(object date)
if (date == null)
return string.Empty;
return date == null ? string.Empty : Convert.ToDateTime(date).ConvertDate();
private static string ConvertToString(object value)
return Convert.ToString(ReturnEmptyIfNull(value));
private static int ConvertToInt(object value)
return Convert.ToInt32(ReturnZeroIfNull(value));
private static long ConvertToLong(object value)
return Convert.ToInt64(ReturnZeroIfNull(value));
private static decimal ConvertToDecimal(object value)
return Convert.ToDecimal(ReturnZeroIfNull(value));
private static DateTime convertToDateTime(object date)
return Convert.ToDateTime(ReturnDateTimeMinIfNull(date));
public static string ConvertDate(this DateTime datetTime, bool excludeHoursAndMinutes = false)
if (datetTime != DateTime.MinValue)
if (excludeHoursAndMinutes)
return datetTime.ToString("yyyy-MM-dd");
return datetTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
return null;
public static object ReturnEmptyIfNull(this object value)
if (value == DBNull.Value)
return string.Empty;
if (value == null)
return string.Empty;
return value;
public static object ReturnZeroIfNull(this object value)
if (value == DBNull.Value)
return 0;
if (value == null)
return 0;
return value;
public static object ReturnDateTimeMinIfNull(this object value)
if (value == DBNull.Value)
return DateTime.MinValue;
if (value == null)
return DateTime.MinValue;
return value;
【讨论】:
【参考方案15】:我知道为时已晚
但实际上在 Newtonsoft Json 的帮助下有一个简单的方法:
var json = JsonConvert.SerializeObject(dataTable);
var YourConvertedDataType = JsonConvert.DeserializeObject<YourDataType>(json);
【讨论】:
以上是关于将 DataTable 转换为 List<T>的主要内容,如果未能解决你的问题,请参考以下文章