DataTable을 일반 목록으로 어떻게 변환합니까?


185

현재, 나는 다음을 사용하고 있습니다 :

DataTable dt = CreateDataTableInSomeWay();

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

더 나은 / 마법적인 방법이 있습니까?


2
DataRowCollection으로 할 수없는 List로 무엇을하려고합니까?
Jason Kealey

광산은 늦었지만 희망이 도움이 될 것입니다. 근무 솔루션 .. stackoverflow.com/a/58607820/9048996
Thameem

답변:


276

.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();

이것을 listjson 으로 변환하는 방법 .
ACP

6
@Pandiya : .NET에서 데이터를 JSON으로 변환하는 방법에는 여러 가지가 있습니다. 개인적으로 나는 항상 JSON.NET 라이브러리를 사용했지만 다른 접근 방식도 있습니다.
Jon Skeet


1
@ Jon Skeet : DataRow에서 값을 얻고 싶습니다. 어떤 방법이 있습니까? list.ItemArray [0]처럼 보이지 않습니다.
Ramesh Durai

@Jon, FYI : dt.AsEnumerable (). ToList () 'System.Data.EnumerableRowCollection <System.Data.DataRow>'에 'ToList'에 대한 정의가 포함되어 있지 않습니다
Pradip

66
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();

위의 코드는 BCs에서 작동하지 않을 수 있습니다. dt.Rows는 'AsEnumerable'을 구현하지 않았습니다. emp = (dt.AsEnumerable ()의 DataRow 행에서 새 직원 선택 {_FirstName = row [ "FirstName"]. ToString (), _LastName = row [ "Last_Name"]. ToString ()}) .ToList ();
Navin Pandit

37

C # 3.0 및 System.Data.DataSetExtensions.dll을 사용하면

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

3
이렇게하면 데이터 행에서 foreach를 50 % 만 사용하여 성능을 향상시킬 수 있습니다.
lloydom

33

당신은 사용할 수 있습니다

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

dt.Select()는 테이블의 모든 행을 데이터 행의 배열로 반환하고 List생성자는 해당 객체 배열을 인수로 받아 들여 처음에 목록을 채 웁니다.


Select ()에는 매개 변수가 필요하지 않습니다. 매개 변수가없는 과부하는 모든 행을 반환합니다.
Kon

감사합니다. 귀하의 의견에 맞게 답변을 조정 해주세요
Kibbee

15

확장 기능을 다음과 같이 만들 수 있습니다.

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>();

작동하지 않습니다 -dotnetfiddle.net/I22r2c 참조 Reflection 사용이 느리고 성능 결정적 코드에서 권장되지 않습니다.
Almenon

열에 대한 데이터 유형 정보를 추가해야합니다. DataTable dt = 새로운 DataTable (); dt.Columns.Add ( "id", typeof (Int32)); dt.Columns.Add ( "name", typeof (String)); dt.Columns.Add ( "foo", typeof (DateTime)); for (int i = 0; i <= 1000; i ++) {dt.Rows.Add (i, "foo", DateTime.Now);}
Rahul Garg

지금 작동합니다. 감사.
Almenon

14

"ID"int 필드의 값 목록 만 반환하려면 다음을 사용할 수 있습니다.

List<int> ids = (from row in dt.AsEnumerable() select Convert.ToInt32(row["ID"])).ToList();

12

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;
}

struct에서도 작동 할 수 있기 때문에 클래스를 제거했습니다.
미키 Perlstein

이것은 잘 작동합니다. 누군가가 코드를 가지고 놀고 싶다면이 링크에서 .net 바이올린을 만들었습니다. dotnetfiddle.net/mTKevy
Almenon

@Almenon 나는 작은 수정을 추가했습니다, 그것은 약간의 성능을 향상시켜야합니다
Bondaryuk Vladimir

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();

훌륭한! 당신은 내 하루를 저장
Anynomous Khan



4

좀 더 '매직'방식이며 .NET 3.5가 필요하지 않습니다.

예를 들어 DBDatatableGuids의 단일 열 (SQL의 고유 식별자)을 반환하는 경우 다음을 사용할 수 있습니다.

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

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;
}

3

DataTable.Select() 데이터 테이블에 있던 순서대로 행을 제공하지 않습니다.

순서가 중요하다면 datarow 컬렉션을 반복하고 목록을 작성하는 것이 올바른 방법이거나 오버로드를 사용할 수도 있다고 생각 DataTable.Select(string filterexpression, string sort)합니다.

그러나이 과부하는 SQL이 제공하는 모든 순서 (예 : 순서대로 ...)를 처리하지 못할 수 있습니다.


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});
}

1

System.Data네임 스페이스를 사용 하면 얻을 것이다 .AsEnumerable().


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과 사용자 정의 클래스를 전달하는 두 가지 함수입니다. 그런 다음 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 열의 이름과 클래스 속성 이름이 같아야합니다. 그렇지 않으면이 함수가 제대로 작동하지 않습니다.


1
답변 주셔서 감사합니다. 코드에 간단한 설명과 몇 가지 주석을 추가하면 좋을 것입니다. 이것은 사람들이 귀하의 답변을 더 잘 이해하는 데 도움이됩니다.
Andre Hofmeister

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;

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>

0

우리는 변환하는 일반적인 방법을 사용할 수 있습니다 DataTableList대신 수동으로 변환 DataTableList.

참고 : DataTableColumnNameType의이 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;
    }
}

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;
    }
}

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;
}

0

사용 확장 :

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
}

0

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();

0

DataTable을 클래스의 일반 목록으로 변환하는 가장 쉬운 방법

Newtonsoft.Json 사용;

var json = JsonConvert.SerializeObject(dataTable);
var model = JsonConvert.DeserializeObject<List<ClassName>>(json);

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);

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 예제 링크

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; }
}

}

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.