현재, 나는 다음을 사용하고 있습니다 :
DataTable dt = CreateDataTableInSomeWay();
List<DataRow> list = new List<DataRow>();
foreach (DataRow dr in dt.Rows)
{
list.Add(dr);
}
더 나은 / 마법적인 방법이 있습니까?
현재, 나는 다음을 사용하고 있습니다 :
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
json 으로 변환하는 방법 .
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();
확장 기능을 다음과 같이 만들 수 있습니다.
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>();
nullable 유형의 경우 예외를 반환하기 때문에이 답변 ( https : //.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;
}
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();
다시 3.5를 사용하면 다음과 같이 할 수 있습니다.
dt.Select().ToList()
BRGDS
다음은 DataTable을 일반 목록으로 변환하는 DataTable 확장 메서드입니다.
https://gist.github.com/gaui/a0a615029f1327296cf8
용법:
List<Employee> emp = dtTable.DataTableToList<Employee>();
// 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;
}
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});
}
/* 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과 사용자 정의 클래스를 전달하는 두 가지 함수입니다. 그런 다음 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);
요구 사항에 따라 학생 클래스 이름과 dt 값을 변경하십시오. 이 경우 DataTable 열의 이름과 클래스 속성 이름이 같아야합니다. 그렇지 않으면이 함수가 제대로 작동하지 않습니다.
이것은 나를 위해 일했습니다 : 적어도 .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;
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
.
참고 : DataTable
의 ColumnName
와 Type
의이 PropertyName
동일해야합니다.
아래 메소드를 호출하십시오.
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;
}
}
데이터 테이블에서 일반 목록에 대한 것과 같은 일반적인 방법을 사용할 수 있습니다
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;
}
}
변환 중 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;
}
사용 확장 :
public static class Extensions
{
#region Convert Datatable To List
public static IList<T> ToList<T>(this DataTable table) where T : new()
{
IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
IList<T> result = new List<T>();
foreach (var row in table.Rows)
{
var item = CreateItemFromRow<T>((DataRow)row, properties);
result.Add(item);
}
return result;
}
private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties) where T : new()
{
T item = new T();
foreach (var property in properties)
{
property.SetValue(item, row[property.Name], null);
}
return item;
}
#endregion
}
DataTable 행을 일반 클래스 목록에 할당하려면
List<Candidate> temp = new List<Candidate>();//List that holds the Candidate Class,
//Note:The Candidate class contains RollNo,Name and Department
//tb is DataTable
temp = (from DataRow dr in tb.Rows
select new Candidate()
{
RollNO = Convert.ToInt32(dr["RollNO"]),
Name = dr["Name"].ToString(),
Department = dr["Department"].ToString(),
}).ToList();
DataTable을 클래스의 일반 목록으로 변환하는 가장 쉬운 방법
Newtonsoft.Json 사용;
var json = JsonConvert.SerializeObject(dataTable);
var model = JsonConvert.DeserializeObject<List<ClassName>>(json);
다음 두 가지 일반 함수를 사용할 수 있습니다
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);
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 예제 링크
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; }
}
}