目前,我正在使用:
DataTable dt = CreateDataTableInSomeWay();
List<DataRow> list = new List<DataRow>();
foreach (DataRow dr in dt.Rows)
{
list.Add(dr);
}
有更好的/神奇的方式吗?
答案 0 :(得分:252)
如果您使用的是.NET 3.5,则可以使用DataTableExtensions.AsEnumerable
(扩展方法)然后如果您确实需要List<DataRow>
而不只是IEnumerable<DataRow>
,则可以调用{{ 3}}:
IEnumerable<DataRow> sequence = dt.AsEnumerable();
或
using System.Linq;
...
List<DataRow> list = dt.AsEnumerable().ToList();
答案 1 :(得分:62)
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();
答案 2 :(得分:34)
使用C#3.0和System.Data.DataSetExtensions.dll,
List<DataRow> rows = table.Rows.Cast<DataRow>().ToList();
答案 3 :(得分:31)
您可以使用
List<DataRow> list = new List<DataRow>(dt.Select());
dt.Select()
将返回表中的所有行,作为数据行数组,List
构造函数接受该对象数组作为参数,以便最初填充列表。
答案 4 :(得分:13)
您可以创建扩展功能:
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>();
答案 5 :(得分:12)
如果您只想要返回“ID”int字段中的值列表,可以使用...
List<int> ids = (from row in dt.AsEnumerable() select Convert.ToInt32(row["ID"])).ToList();
答案 6 :(得分:9)
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();
答案 7 :(得分:8)
我在此答案(https://stackoverflow.com/a/24588210/4489664)中添加了一些修改代码,因为对于可为空的类型,它将返回异常
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;
}
答案 8 :(得分:6)
再次使用3.5,你可以这样做:
dt.Select().ToList()
BRGDS
答案 9 :(得分:4)
// 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;
}
答案 10 :(得分:4)
这是一个DataTable扩展方法,它将DataTable转换为通用列表。
https://gist.github.com/gaui/a0a615029f1327296cf8
<强>用法:强>
List<Employee> emp = dtTable.DataTableToList<Employee>();
答案 11 :(得分:4)
更“神奇”的方式,不需要.NET 3.5。
例如,如果DBDatatable
返回一列Guids(SQL中的uniqueidentifier),那么您可以使用:
Dim gList As New List(Of Guid)
gList.AddRange(DirectCast(DBDataTable.Select(), IEnumerable(Of Guid)))
答案 12 :(得分:3)
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});
}
答案 13 :(得分:3)
DataTable.Select()
不会按照数据表中存在的顺序给出行。
如果顺序很重要,我觉得迭代数据行集合并形成一个List是正确的方法,或者你也可以使用DataTable.Select(string filterexpression, string sort)
的重载。
但是这个重载可能无法处理SQL提供的所有排序(如逐个...)。
答案 14 :(得分:2)
将数据表转换为类的通用列表的最简单方法
使用Newtonsoft.Json;
readonly
答案 15 :(得分:1)
使用System.Data
命名空间,您将获得.AsEnumerable()
。
答案 16 :(得分:1)
/* 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
*/
以下是两个函数,如果我们传递一个 数据表 和用户定义的类。 然后它将使用DataTable数据返回该类的List。
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;
}
此方法将检查字段的数据类型,并将dataTable值转换为该数据类型。
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();
}
要调用上述方法,请使用以下语法:
List< Student > studentDetails = new List< Student >();
studentDetails = ConvertDataTable< Student >(dt);
根据您的要求更改学生班级名称和学生值。在这种情况下,DataTable列的名称和类属性名称应该相同,否则此函数将无法正常工作。
答案 17 :(得分:0)
我们可以使用通用方法将DataTable
转换为List
,而不是手动将DataTable
转换为List
。
注意:DataTable
的{{1}}和ColumnName
的{{1}}应该相同。
调用以下方法:
Type
答案 18 :(得分:0)
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>
答案 19 :(得分:0)
https://www.nuget.org/packages/AD.GenericConversion/
检查此库以进行转换,您将在此处找到所有类型的转换,例如: -
答案 20 :(得分:0)
您可以使用通用方法,如将数据表导入通用列表
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;
}
}
答案 21 :(得分:0)
将DataTable
转换为通用Dictionary
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;
}
答案 22 :(得分:0)
使用扩展名:
private func setSizesSliderValue(pn: Int, slider: UISlider, setSliderValue: Bool)
{
if setSliderValue
{
slider.setValue(Float(pn), animated: true)
}
masterPresetInfoLabel.text = String(
format: TexturingViewController.createAndSendPresetNumberNofiticationTemplate,
self.currentPresetNumber.name.uppercased(),
String(self.currentPresetNumber.currentUserIndexHumanFriendly)
)
}
@objc func presetNumberSliderTouchUp(_ sender: Any)
{
guard let slider = sender as? NormalSlider else{
return
}
setupSliderChangedValuesGeneric(slider: slider, setSliderValue: true)
}
private func setupSliderChangedValuesGeneric(slider: NormalSlider, setSliderValue: Bool)
{
let rounded = roundf((Float(slider.value) / Float(presetNumberStep))) * Float(presetNumberStep)
// Set new preset number value
self.currentPresetNumber.current = Int(rounded)
setSizesSliderValue(pn: Int(rounded), slider: slider, setSliderValue: setSliderValue)
}
@IBAction func presetNumberChanged(_ sender: Any)
{
guard let slider = sender as? NormalSlider else{
return
}
setupSliderChangedValuesGeneric(slider: slider, setSliderValue: false)
}
答案 23 :(得分:0)
要将DataTable行分配给类的通用列表
y =( moment('Mon 03-Jul-2017, 11:00 AM', 'ddd DD-MMM-YYYY, hh:mm A').format('hh:mm A') );
x= ( moment('Mon 03-Jul-2017, 11:00 PM', 'ddd DD-MMM-YYYY, hh:mm A').format('hh:mm A') );
console.log(x>y)
答案 24 :(得分:0)
这对我有用: 至少需要.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;
答案 25 :(得分:0)
您可以使用以下两个通用函数
private 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())
{
if (pro.Name == column.ColumnName)
pro.SetValue(obj, dr[column.ColumnName].ToString(), null);
else
continue;
}
}
return obj;
}
并按照以下说明使用它
List<StudentScanExamsDTO> studentDetails = ConvertDataTable<StudentScanExamsDTO>(dt);
答案 26 :(得分:0)
lPerson = dt.AsEnumerable().Select(s => new Person()
{
Name = s.Field<string>("Name"),
SurName = s.Field<string>("SurName"),
Age = s.Field<int>("Age"),
InsertDate = s.Field<DateTime>("InsertDate")
}).ToList();
链接到有效的DotNetFiddle Example
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Data.DataSetExtensions;
public static void Main()
{
DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("SurName", typeof(string));
dt.Columns.Add("Age", typeof(int));
dt.Columns.Add("InsertDate", typeof(DateTime));
var row1= dt.NewRow();
row1["Name"] = "Adam";
row1["SurName"] = "Adam";
row1["Age"] = 20;
row1["InsertDate"] = new DateTime(2020, 1, 1);
dt.Rows.Add(row1);
var row2 = dt.NewRow();
row2["Name"] = "John";
row2["SurName"] = "Smith";
row2["Age"] = 25;
row2["InsertDate"] = new DateTime(2020, 3, 12);
dt.Rows.Add(row2);
var row3 = dt.NewRow();
row3["Name"] = "Jack";
row3["SurName"] = "Strong";
row3["Age"] = 32;
row3["InsertDate"] = new DateTime(2020, 5, 20);
dt.Rows.Add(row3);
List<Person> lPerson = new List<Person>();
lPerson = dt.AsEnumerable().Select(s => new Person()
{
Name = s.Field<string>("Name"),
SurName = s.Field<string>("SurName"),
Age = s.Field<int>("Age"),
InsertDate = s.Field<DateTime>("InsertDate")
}).ToList();
foreach(Person pers in lPerson)
{
Console.WriteLine("{0} {1} {2} {3}", pers.Name, pers.SurName, pers.Age, pers.InsertDate);
}
}
public class Person
{
public string Name { get; set; }
public string SurName { get; set; }
public int Age { get; set; }
public DateTime InsertDate { get; set; }
}
}
答案 27 :(得分:0)
如果有人想创建自定义函数以将数据表转换为列表
class Program
{
static void Main(string[] args)
{
DataTable table = GetDataTable();
var sw = new Stopwatch();
sw.Start();
LinqMethod(table);
sw.Stop();
Console.WriteLine("Elapsed time for Linq Method={0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
ForEachMethod(table);
sw.Stop();
Console.WriteLine("Elapsed time for Foreach method={0}", sw.ElapsedMilliseconds);
Console.ReadKey();
}
private static DataTable GetDataTable()
{
var table = new DataTable();
table.Columns.Add("ID", typeof(double));
table.Columns.Add("CategoryName", typeof(string));
table.Columns.Add("Active", typeof(double));
var rand = new Random();
for (int i = 0; i < 100000; i++)
{
table.Rows.Add(i, "name" + i, rand.Next(0, 2));
}
return table;
}
private static void LinqMethod(DataTable table)
{
var list = table.AsEnumerable()
.Skip(1)
.Select(dr =>
new Category
{
Id = Convert.ToInt32(dr.Field<double>("ID")),
CategoryName = dr.Field<string>("CategoryName"),
IsActive =
dr.Field<double>("Active") == 1 ? true : false
}).ToList();
}
private static void ForEachMethod(DataTable table)
{
var categoryList = new List<Category>(table.Rows.Count);
foreach (DataRow row in table.Rows)
{
var values = row.ItemArray;
var category = new Category()
{
Id = Convert.ToInt32(values[0]),
CategoryName = Convert.ToString(values[1]),
IsActive = (double)values[2] == 1 ? true : false
};
categoryList.Add(category);
}
}
private class Category
{
public int Id { get; set; }
public string CategoryName { get; set; }
public bool IsActive { get; set; }
}
}
如果执行上述代码,Foreach方法将在56毫秒内完成,而linq 1则需要101毫秒(用于1000条记录)。 因此,Foreach方法更好用。 来源:Ways to Convert Datatable to List in C# (with performance test example)