Как преобразовать DataTable в общий список? - PullRequest
166 голосов
/ 16 октября 2008

В настоящее время я использую:

DataTable dt = CreateDataTableInSomeWay();

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

Есть ли лучший / волшебный способ?

Ответы [ 22 ]

253 голосов
/ 16 октября 2008

Если вы используете .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();
63 голосов
/ 15 декабря 2011
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();
34 голосов
/ 16 октября 2008

С C # 3.0 и System.Data.DataSetExtensions.dll,

List<DataRow> rows = table.Rows.Cast<DataRow>().ToList();
31 голосов
/ 16 октября 2008

Вы можете использовать

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

dt.Select() вернет все строки в вашей таблице в виде массива данных, а конструктор List принимает этот массив объектов в качестве аргумента для первоначального заполнения списка.

13 голосов
/ 26 апреля 2015

Вы можете создать функцию расширения как:

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>();
12 голосов
/ 10 октября 2012

Если вы просто хотите получить список значений из возвращаемого поля int, вы можете использовать ...

List<int> ids = (from row in dt.AsEnumerable() select Convert.ToInt32(row["ID"])).ToList();
9 голосов
/ 31 июля 2012
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();
8 голосов
/ 14 апреля 2015

Я добавил некоторую модификацию в код из этого ответа (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;
}
6 голосов
/ 15 марта 2010

Опять же, используя 3.5, вы можете сделать это следующим образом:

dt.Select().ToList()

BRGDS

4 голосов
/ 23 июля 2013
// 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...