如何将DataTable转换为通用列表?

目前,我正在使用:

DataTable dt = CreateDataTableInSomeWay(); List<DataRow> list = new List<DataRow>(); foreach (DataRow dr in dt.Rows) { list.Add(dr); } 

有更好的/神奇的方法吗?

如果您使用.NET 3.5,则可以使用DataTableExtensions.AsEnumerable (扩展方法),如果您确实需要List<DataRow>而不是IEnumerable<DataRow> ,则可以调用Enumerable.ToList

 IEnumerable<DataRow> sequence = dt.AsEnumerable(); 

要么

 using System.Linq; ... List<DataRow> list = dt.AsEnumerable().ToList(); 
 List<Employee> emp = new List<Employee>(); //Maintaining DataTable on ViewState //For Demo only DataTable dt = ViewState["CurrentEmp"] as DataTable; //read data from DataTable //using lamdaexpression emp = (from DataRow row in dt.Rows select new Employee { _FirstName = row["FirstName"].ToString(), _LastName = row["Last_Name"].ToString() }).ToList(); 

使用C#3.0和System.Data.DataSetExtensions.dll,

 List<DataRow> rows = table.Rows.Cast<DataRow>().ToList(); 

你可以使用

 List<DataRow> list = new List<DataRow>(dt.Select()); 

dt.Select()将返回表中的所有行,作为数据行数组, List构造函数接受该对象数组作为初始填充列表的参数。

如果你只是想从返回的“ID”int字段的值的列表,你可以使用…

 List<int> ids = (from row in dt.AsEnumerable() select Convert.ToInt32(row["ID"])).ToList(); 
 using System.Data; var myEnumerable = myDataTable.AsEnumerable(); List<MyClass> myClassList = (from item in myEnumerable select new MyClass{ MyClassProperty1 = item.Field<string>("DataTableColumnName1"), MyClassProperty2 = item.Field<string>("DataTableColumnName2") }).ToList(); 

你可以创build一个扩展函数为:

 public static List<T> ToListof<T>(this DataTable dt) { const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; var columnNames = dt.Columns.Cast<DataColumn>() .Select(c => c.ColumnName) .ToList(); var objectProperties = typeof(T).GetProperties(flags); var targetList = dt.AsEnumerable().Select(dataRow => { var instanceOfT = Activator.CreateInstance<T>(); foreach (var properties in objectProperties.Where(properties => columnNames.Contains(properties.Name) && dataRow[properties.Name] != DBNull.Value)) { properties.SetValue(instanceOfT, dataRow[properties.Name], null); } return instanceOfT; }).ToList(); return targetList; } var output = yourDataInstance.ToListof<targetModelType>(); 

再次使用3.5,你可以这样做:

 dt.Select().ToList() 

BRGDS

更“神奇”的方式,并不需要.NET 3.5。

例如,如果DBDatatable返回一列Guid(SQL中的uniqueidentifier),那么您可以使用:

 Dim gList As New List(Of Guid) gList.AddRange(DirectCast(DBDataTable.Select(), IEnumerable(Of Guid))) 

DataTable.Select()不会按照它们在数据表中存在的顺序给出行。

如果顺序是重要的,我觉得遍历数据收集和形成一个列表是正确的路要走,或者你也可以使用重载DataTable.Select(string filterexpression, string sort)

但是,这个重载可能无法处理SQL提供的所有顺序(比如按顺序排列)。

 // this is better suited for expensive object creation/initialization IEnumerable<Employee> ParseEmployeeTable(DataTable dtEmployees) { var employees = new ConcurrentBag<Employee>(); Parallel.ForEach(dtEmployees.AsEnumerable(), (dr) => { employees.Add(new Employee() { _FirstName = dr["FirstName"].ToString(), _LastName = dr["Last_Name"].ToString() }); }); return employees; } 

我从这个答案( https://stackoverflow.com/a/24588210/4489664 )一些修改后的代码,因为当我在我的class级中使用可空的DateTime它返回错误

 public static List<T> DataTableToList<T>(this DataTable table) where T : class, new() { try { T tempT = new T(); var tType = tempT.GetType(); List<T> list = new List<T>(); foreach (var row in table.Rows.Cast<DataRow>()) { T obj = new T(); foreach (var prop in obj.GetType().GetProperties()) { var propertyInfo = tType.GetProperty(prop.Name); var rowValue = row[prop.Name]; var t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; try { object safeValue = (rowValue == null || DBNull.Value.Equals(rowValue)) ? null : Convert.ChangeType(rowValue, t); propertyInfo.SetValue(obj, safeValue, null); } catch (Exception ex) {//this write exception to my logger _logger.Error(ex.Message); } } list.Add(obj); } return list; } catch { return null; } } 
 DataTable dt; // datatable should contains datacolumns with Id,Name List<Employee> employeeList=new List<Employee>(); // Employee should contain EmployeeId, EmployeeName as properties foreach (DataRow dr in dt.Rows) { employeeList.Add(new Employee{EmployeeId=dr.Id,EmplooyeeName=dr.Name}); } 

这里有一个DataTable扩展方法,用于将DataTable转换为通用列表。

https://gist.github.com/gaui/a0a615029f1327296cf8

用法:

 List<Employee> emp = dtTable.DataTableToList<Employee>(); 

这工作对我来说:至less需要.NET Framework 3.5, 下面的代码显示DataRow转向Generic.IEnumerable,comboBox1已被用于更好的说明。

 using System.Linq; DataTable dt = new DataTable(); dt = myClass.myMethod(); List<object> list = (from row in dt.AsEnumerable() select (row["name"])).ToList(); comboBox1.DataSource = list; 

使用System.Data命名空间,那么你将得到.AsEnumerable()

产量

 public class ModelUser { #region Model private string _username; private string _userpassword; private string _useremail; private int _userid; /// <summary> /// /// </summary> public int userid { set { _userid = value; } get { return _userid; } } /// <summary> /// /// </summary> public string username { set { _username = value; } get { return _username; } } /// <summary> /// /// </summary> public string useremail { set { _useremail = value; } get { return _useremail; } } /// <summary> /// /// </summary> public string userpassword { set { _userpassword = value; } get { return _userpassword; } } #endregion Model } public List<ModelUser> DataTableToList(DataTable dt) { List<ModelUser> modelList = new List<ModelUser>(); int rowsCount = dt.Rows.Count; if (rowsCount > 0) { ModelUser model; for (int n = 0; n < rowsCount; n++) { model = new ModelUser(); model.userid = (int)dt.Rows[n]["userid"]; model.username = dt.Rows[n]["username"].ToString(); model.useremail = dt.Rows[n]["useremail"].ToString(); model.userpassword = dt.Rows[n]["userpassword"].ToString(); modelList.Add(model); } } return modelList; } static DataTable GetTable() { // Here we create a DataTable with four columns. DataTable table = new DataTable(); table.Columns.Add("userid", typeof(int)); table.Columns.Add("username", typeof(string)); table.Columns.Add("useremail", typeof(string)); table.Columns.Add("userpassword", typeof(string)); // Here we add five DataRows. table.Rows.Add(25, "Jame", "Jame@hotmail.com", DateTime.Now.ToString()); table.Rows.Add(50, "luci", "luci@hotmail.com", DateTime.Now.ToString()); table.Rows.Add(10, "Andrey", "Andrey@hotmail.com", DateTime.Now.ToString()); table.Rows.Add(21, "Michael", "Michael@hotmail.com", DateTime.Now.ToString()); table.Rows.Add(100, "Steven", "Steven@hotmail.com", DateTime.Now.ToString()); return table; } protected void Page_Load(object sender, EventArgs e) { List<ModelUser> userList = new List<ModelUser>(); DataTable dt = GetTable(); userList = DataTableToList(dt); gv.DataSource = userList; gv.DataBind(); }[enter image description here][1] 
 </asp:GridView> </div> 

我们可以使用通用方法将DataTable转换为List而不是手动将DataTable转换为List

注意: DataTableColumnNameTypePropertyName应该是相同的。

调用下面的方法:

 long result = Utilities.ConvertTo<Student>(dt ,out listStudent); // Generic Method public class Utilities { public static long ConvertTo<T>(DataTable table, out List<T> entity) { long returnCode = -1; entity = null; if (table == null) { return -1; } try { entity = ConvertTo<T>(table.Rows); returnCode = 0; } catch (Exception ex) { returnCode = 1000; } return returnCode; } static List<T> ConvertTo<T>(DataRowCollection rows) { List<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; } static T CreateItem<T>(DataRow row) { string str = string.Empty; string strObj = string.Empty; T obj = default(T); if (row != null) { obj = Activator.CreateInstance<T>(); strObj = obj.ToString(); NameValueCollection objDictionary = new NameValueCollection(); foreach (DataColumn column in row.Table.Columns) { PropertyInfo prop = obj.GetType().GetProperty(column.ColumnName); if (prop != null) { str = column.ColumnName; try { objDictionary.Add(str, row[str].ToString()); object value = row[column.ColumnName]; Type vType = obj.GetType(); if (value == DBNull.Value) { if (vType == typeof(int) || vType == typeof(Int16) || vType == typeof(Int32) || vType == typeof(Int64) || vType == typeof(decimal) || vType == typeof(float) || vType == typeof(double)) { value = 0; } else if (vType == typeof(bool)) { value = false; } else if (vType == typeof(DateTime)) { value = DateTime.MaxValue; } else { value = null; } prop.SetValue(obj, value, null); } else { prop.SetValue(obj, value, null); } } catch(Exception ex) { } } } PropertyInfo ActionProp = obj.GetType().GetProperty("ActionTemplateValue"); if (ActionProp != null) { object ActionValue = objDictionary; ActionProp.SetValue(obj, ActionValue, null); } } return obj; } }