Bir DataTable'ı genel bir listeye nasıl dönüştürürsünüz?


185

Şu anda kullanıyorum:

DataTable dt = CreateDataTableInSomeWay();

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

Daha iyi / sihirli bir yol var mı?


2
DataRowCollection öğenizle yapamayacağınız bir Liste ile ne yapmaya çalışıyorsunuz?
Jason Kealey

Benimki geç ama umut faydalı olacak. Çalışma çözümü .. stackoverflow.com/a/58607820/9048996
Thameem

Yanıtlar:


276

.NET 3.5 kullanıyorsanız, DataTableExtensions.AsEnumerable(bir uzantı yöntemi) kullanabilirsiniz ve List<DataRow>bunun yerine gerçekten bir yerine ihtiyacınız varsa IEnumerable<DataRow>arayabilirsiniz Enumerable.ToList:

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

veya

using System.Linq;
...
List<DataRow> list = dt.AsEnumerable().ToList();

nasıl listjson dönüştürmek için.
ACP

6
@Pandiya: Verileri .NET'te JSON'a dönüştürmenin çeşitli yolları vardır. Şahsen ben her zaman JSON.NET kütüphanesini kullandım, ama başka yaklaşımlar da var.
Jon Skeet


1
@Jon Skeet: Değeri DataRow'da almak istiyorum. Herhangi bir yöntem var mı? List.ItemArray [0] gibi almak yerine.
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();

Yukarıdaki kod bcs çalışmayabilir. dt.Rows 'AsEnumerable' uygulamasını uygulamadı. Bu aşağıdaki gibi düzeltilebilir: emp = (dt.AsEnumerable () içindeki DataRow satırından yeni Çalışan seçin {_FirstName = satır ["Adı"]. ToString (), _LastName = satır ["Last_Name"]. ToString ()}) .Listeye();
Navin Pandit

37

C # 3.0 ve System.Data.DataSetExtensions.dll ile,

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

3
bunu yapmak performansın bir veri satırında sadece bir foreach kullanmasını% 50 oranında artırdı.
lloydom

33

Kullanabilirsin

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

dt.Select()tablonuzdaki tüm satırları bir datarows dizisi olarak döndürür ve Listyapıcı bu nesne dizisini başlangıçta listenizi doldurmak için bir argüman olarak kabul eder.


Select () için herhangi bir parametre gerekmez. Parametresiz aşırı yük tüm satırları döndürür.
Kon

Teşekkürler, sugguestion uyacak şekilde cevabımı ayarlayarak
Kibbee

15

Bir uzantı işlevi şu şekilde oluşturabilirsiniz:

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

Çalışmıyor - bkz. Dotnetfiddle.net/I22r2c Reflection kullanımının yavaş olduğu ve performans açısından kritik kodda önerilmediği de unutulmamalıdır.
Almenon

Sütunlar için veri türü bilgileri eklemeniz gerekir. DataTable dt = yeni DataTable (); dt.Columns.Add ("id", typeof (Int32)); dt.Columns.Add ( "ad" typeof (String)); dt.Columns.Add ("foo", typeof (DateTime)); for (int i = 0; i <= 1000; i ++) {dt.Rows.Add (i, "foo", DateTime.Now);}
Rahul Garg

Şimdi çalışıyor. Teşekkürler.
Almenon

14

Yalnızca "ID" int alanındaki değerlerin bir listesini döndürmek istiyorsanız şunu kullanabilirsiniz ...

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

12

Bu cevaptan ( https://stackoverflow.com/a/24588210/4489664 ) koda bazı değişiklikler ekledim çünkü null olabilecek Türler için istisna dönecek

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

Sınıfı da kaldırdım çünkü yapı ile de çalışabilir.
Mickey Perlstein

Bu gayet iyi çalışıyor, iyi iş. Herkes kod ile oynamak istiyorsa, ben bu bağlantıda bir .net keman yarattı: dotnetfiddle.net/mTKevy
Almenon

Küçük değişiklik ekledim, performansı biraz artırmalıyız
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();

Parlak!
Günümü



4

Daha 'sihirli' bir yol ve .NET 3.5'e ihtiyaç duymaz.

Örneğin, DBDatatabletek bir Kılavuz sütunu (SQL'de uniqueidentifier) ​​döndürüyorsanız şunu kullanabilirsiniz:

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() Satırları veri tablosunda bulundukları sırayla vermez.

Eğer sipariş önemli ise veri toplama üzerinde yineleme hissediyorum ve bir Liste oluşturmak için doğru yoludur ya da aşırı yük kullanabilirsiniz DataTable.Select(string filterexpression, string sort).

Ancak bu aşırı yükleme, SQL'in sağladığı tüm siparişleri (duruma göre ... gibi) ele almayabilir.


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

Ad System.Dataalanını kullanın o zaman alacaksınız .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 ve kullanıcı tanımlı bir sınıf geçirirsek iki fonksiyon aşağıdadır. Daha sonra DataTable verileriyle bu sınıfın Listesini döndürür.

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

Bu yöntem, alanın veri türünü kontrol eder ve dataTable değerini bu veri türüne dönüştürür.

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

Önceki yöntemi çağırmak için aşağıdaki sözdizimini kullanın:

List< Student > studentDetails = new List< Student >();  
studentDetails = ConvertDataTable< Student >(dt); 

Öğrenci sınıfı adını ve dt değerini gereksinimlerinize göre değiştirin. Bu durumda, DataTable sütununun adı ve sınıf özelliği adı aynı olmalıdır, aksi takdirde bu işlev düzgün çalışmaz.


1
Cevabınız için teşekkürler. Kodunuza kısa bir açıklama ve birkaç yorum da eklemek harika olurdu. Bu, insanların cevabınızı daha iyi anlamalarına yardımcı olur.
Andre Hofmeister

0

Bu benim için çalıştı: En azından .Net Framework 3.5, aşağıdaki Kod DataRow Generic.Inerable, comboBox1 daha iyi bir örnek için döndü görüntüler.

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

Çıktı

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

Manuel olarak dönüştürmek yerine dönüştürmek DataTableiçin Genel Yöntem kullanabiliriz .ListDataTableList .

Not: DataTable's ColumnNameve Type' sPropertyName aynı olmalıdır.

Aşağıdaki Yöntemi arayın:

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

Genel listeye datatable için böyle bir genel yöntem kullanabilirsiniz

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

Dönüştürme DataTableGenericDictionary

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

Uzantıyı Kullan:

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 satırlarını genel sınıf listesine atamak için

  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'ı Generic sınıf listesine dönüştürmenin en kolay yolu

Newtonsoft.Json kullanarak;

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

0

aşağıdaki iki Genel işlevi kullanabilirsiniz

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

ve aşağıdaki gibi kullanın

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

Çalışan DotNetFiddle Örneği bağlantısı

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

}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.