2008-10-16 2 views
145

В настоящее время я использую:Как преобразовать DataTable в общий список?

DataTable dt = CreateDataTableInSomeWay(); 

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

Есть ли лучше/магия путь?

+2

Что вы пытаетесь выполнить с помощью списка, который вы не можете сделать с помощью DataRowCollection? – 2008-10-16 13:25:09

ответ

223

Если вы используете .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(); 
+0

Splendid. Точно, что я был после. Спасибо всем за ответы. – 2008-10-16 14:08:21

+0

как преобразовать этот `list` в json. – 2010-08-14 05:50:39

+6

@Pandiya: Существуют различные способы преобразования данных в JSON в .NET. Лично я всегда использовал библиотеку JSON.NET, но есть и другие подходы. – 2010-08-14 07:33:09

29

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

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

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

+0

Выбрать() не требуется никаких параметров. Безпараметрическая перегрузка вернет все строки. – Kon 2008-10-16 13:29:12

+0

Спасибо, отрегулировав мой ответ, чтобы он соответствовал вашему предложению – Kibbee 2008-10-16 13:30:37

+0

Это работает в .Net 2.0, а также – JPProgrammer 2015-10-16 03:37:44

33

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

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

. Это помогло производительности от простого использования foreach над datarow на 50% времени. – lloydom 2012-02-24 10:04:02

4

Более «волшебный» способ, и не нужен .NET 3.5.

Если, например, DBDatatable возвращался один столбец Guids (UniqueIdentifier в SQL), то вы можете использовать:

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

DataTable.Select() оленья кожа дать Ряды в порядке, они присутствовали в DataTable.

Если заказ важен, я чувствую, что итерация по коллекции datarow и формирование списка - это правильный путь, или вы также можете использовать перегруз DataTable.Select(string filterexpression, string sort).

Но эта перегрузка может не обрабатывать все заказы (например, по порядку ...), которые предоставляет SQL.

6

Опять же, с помощью 3,5 вы можете сделать это нравится:

dt.Select().ToList() 

BRGDS

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

Если вы просто хотите получить список значений из "ID" ИНТ поле вернулся, вы можно использовать ...

List<int> ids = (from row in dt.AsEnumerable() select Convert.ToInt32(row["ID"])).ToList(); 
2
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}); 
} 
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; 
} 
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; 
3

Я некоторые модифицированный код из этого ответа (https://stackoverflow.com/a/24588210/4489664), потому что, когда я использовал обнуляемый DateTime в моем классе он возвратил ошибку

public static List<T> DataTableToList<T>(this DataTable table) where T : class, new() 
{ 
    try 
    { 
     T tempT = new T(); 
     var tType = tempT.GetType(); 
     List<T> list = new List<T>(); 
     foreach (var row in table.Rows.Cast<DataRow>()) 
     { 
      T obj = new T(); 
      foreach (var prop in obj.GetType().GetProperties()) 
      { 
       var propertyInfo = tType.GetProperty(prop.Name); 
       var rowValue = row[prop.Name]; 
       var t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; 

       try 
       { 
        object safeValue = (rowValue == null || DBNull.Value.Equals(rowValue)) ? null : Convert.ChangeType(rowValue, t); 
        propertyInfo.SetValue(obj, safeValue, null); 

       } 
       catch (Exception ex) 
       {//this write exception to my logger 
        _logger.Error(ex.Message); 
       } 
      } 
      list.Add(obj); 
     } 
     return list; 
    } 
    catch 
    { 
     return null; 
    } 
} 
0

Используйте System.Data пространство имен, то вы получите .AsEnumerable().

10

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

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

Output

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", "[email protected]", DateTime.Now.ToString()); 
    table.Rows.Add(50, "luci", "[email protected]", DateTime.Now.ToString()); 
    table.Rows.Add(10, "Andrey", "[email protected]", DateTime.Now.ToString()); 
    table.Rows.Add(21, "Michael", "[email protected]", DateTime.Now.ToString()); 
    table.Rows.Add(100, "Steven", "[email protected]", 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

Мы можем использовать метод Generic для преобразования DataTable в List вместо того, чтобы вручную Conver ting a 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; 
    } 
} 
0
 /* 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.

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

Изменение имя класса Student и значение дта на основе ваших требований.В этом случае имя столбца DataTable и имя свойства класса должны быть одинаковыми, иначе эта функция не будет работать должным образом.

0

https://www.nuget.org/packages/AD.GenericConversion/

Checkout эту библиотеку для преобразования вы узнаете все виды преобразования здесь, как: -

  1. DataTable к GenericList
  2. Общий вид на DataTable
  3. Json в DataTable , Общий список, общий тип
  4. данные для Json
Смежные вопросы