How do you convert a DataTable into a generic list?
目前,我正在使用:
1 2 3 4 5 6 7 | DataTable dt = CreateDataTableInSomeWay(); List<DataRow> list = new List<DataRow>(); foreach (DataRow dr in dt.Rows) { list.Add(dr); } |
有更好/神奇的方法吗?
如果您使用.NET 3.5,则可以使用
1 | IEnumerable<DataRow> sequence = dt.AsEnumerable(); |
或
1 2 3 | using System.Linq; ... List<DataRow> list = dt.AsEnumerable().ToList(); |
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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.datasetensions.dll,
1 | List<DataRow> rows = table.Rows.Cast<DataRow>().ToList(); |
号
你可以用
1 |
您可以将扩展函数创建为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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>(); |
号
如果只想返回"id"int字段中的值列表,可以使用…
1 | List<int> ids = (from row in dt.AsEnumerable() select Convert.ToInt32(row["ID"])).ToList(); |
。
1 2 3 4 5 6 7 8 9 10 11 | 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(); |
我已经从这个答案(https://stackoverflow.com/a/24588210/4489664)对代码进行了一些修改,因为对于可以为空的类型,它将返回异常
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 | public static List<T> DataTableToList<T>(this DataTable table) where T: new() { List<T> list = new List<T>(); var typeProperties = typeof(T).GetProperties().Select(propertyInfo => new { PropertyInfo = propertyInfo, Type = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType }).ToList(); foreach (var row in table.Rows.Cast<DataRow>()) { T obj = new T(); foreach (var typeProperty in typeProperties) { object value = row[typeProperty.PropertyInfo.Name]; object safeValue = value == null || DBNull.Value.Equals(value) ? null : Convert.ChangeType(value, typeProperty.Type); typeProperty.PropertyInfo.SetValue(obj, safeValue, null); } list.Add(obj); } return list; } |
号
同样,使用3.5,您可以这样做:
1 | dt.Select().ToList() |
。
BRGDS
下面是一个将数据表转换为泛型列表的数据表扩展方法。
https://gist.github.com/gaui/a0a615029f13272996cf8
用途:
1 | List<Employee> emp = dtTable.DataTableToList<Employee>(); |
号
更"神奇"的方式,不需要.NET 3.5。
例如,如果
1 2 | Dim gList As New List(Of Guid) gList.AddRange(DirectCast(DBDataTable.Select(), IEnumerable(Of Guid))) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // 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; } |
。
如果顺序很重要,我觉得遍历数据行集合并形成一个列表是正确的方法,或者您也可以使用EDOCX1的重载(8)。
但这种重载可能无法处理SQL提供的所有排序(如按大小写排序…)。
1 2 3 4 5 6 7 8 |
使用
1 2 3 4 5 6 7 8 9 | /* This is a generic method that will convert any type of DataTable to a List * * * Example : List< Student > studentDetails = new List< Student >(); * studentDetails = ConvertDataTable< Student >(dt); * * Warning : In this case the DataTable column's name and class property name * should be the same otherwise this function will not work properly */ |
号
The following are the two functions in which if we pass a
DataTable
and a user defined class.
It will then return the List of that class with the DataTable data.
号
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 | public static List<T> ConvertDataTable<T>(DataTable dt) { List<T> data = new List<T>(); foreach (DataRow row in dt.Rows) { T item = GetItem<T>(row); data.Add(item); } return data; } private static T GetItem<T>(DataRow dr) { Type temp = typeof(T); T obj = Activator.CreateInstance<T>(); foreach (DataColumn column in dr.Table.Columns) { foreach (PropertyInfo pro in temp.GetProperties()) { //in case you have a enum/GUID datatype in your model //We will check field's dataType, and convert the value in it. if (pro.Name == column.ColumnName){ try { var convertedValue = GetValueByDataType(pro.PropertyType, dr[column.ColumnName]); pro.SetValue(obj, convertedValue, null); } catch (Exception e) { //ex handle code throw; } //pro.SetValue(obj, dr[column.ColumnName], null); } else continue; } } return obj; } |
号
This method will check the datatype of field, and convert dataTable value in to that datatype.
号
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 | private static object GetValueByDataType(Type propertyType, object o) { if (o.ToString() =="null") { return null; } if (propertyType == (typeof(Guid)) || propertyType == typeof(Guid?)) { return Guid.Parse(o.ToString()); } else if (propertyType == typeof(int) || propertyType.IsEnum) { return Convert.ToInt32(o); } else if (propertyType == typeof(decimal) ) { return Convert.ToDecimal(o); } else if (propertyType == typeof(long)) { return Convert.ToInt64(o); } else if (propertyType == typeof(bool) || propertyType == typeof(bool?)) { return Convert.ToBoolean(o); } else if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?)) { return Convert.ToDateTime(o); } return o.ToString(); } |
To call the preceding method, use the following syntax:
号
1 2 | List< Student > studentDetails = new List< Student >(); studentDetails = ConvertDataTable< Student >(dt); |
。
Change the Student class name and dt value based on your requirements. In this case the DataTable column's name and class property name should be the same otherwise this function will not work properly.
号
将
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static Dictionary<object,IList<dynamic>> DataTable2Dictionary(DataTable dt) { Dictionary<object, IList<dynamic>> dict = new Dictionary<dynamic, IList<dynamic>>(); foreach(DataColumn column in dt.Columns) { IList<dynamic> ts = dt.AsEnumerable() .Select(r => r.Field<dynamic>(column.ToString())) .ToList(); dict.Add(column, ts); } return dict; } |
号
这对我很有用:至少需要.NET Framework 3.5,下面的代码显示的数据行变为generic.ienumerable,ComboBox1用于更好的说明。
1 2 3 4 5 6 | 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; |
号
产量
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 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","[email protected]", DateTime.Now.ToString()); table.Rows.Add(50,"luci","[email protected]", DateTime.Now.ToString()); table.Rows.Add(10,"Andrey","[email protected]", DateTime.Now.ToString()); table.Rows.Add(21,"Michael","[email protected]", DateTime.Now.ToString()); table.Rows.Add(100,"Steven","[email protected]", 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] |
号
1 | </asp:GridView> |
号
我们可以使用通用方法将
注:
调用以下方法:
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 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; } } |
号
https://www.nuget.org/packages/ad.genericConversion网站/
签出此库进行转换,您将在此处找到所有类型的转换,如:
您可以使用类似这样的泛型方法将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 | public static List<T> DataTableToList<T>(this DataTable table) where T : class, new() { try { List<T> list = new List<T>(); foreach (var row in table.AsEnumerable()) { T obj = new T(); foreach (var prop in obj.GetType().GetProperties()) { try { PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name); if (propertyInfo.PropertyType.IsEnum) { propertyInfo.SetValue(obj, Enum.Parse(propertyInfo.PropertyType, row[prop.Name].ToString())); } else { propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null); } } catch { continue; } } list.Add(obj); } return list; } catch { return null; } } |
号