2009-09-15 38 views
36

Tengo una DataTable fuertemente tipada del tipo MyType, me gustaría convertirla en un List<MyType>.Convertir DataTable a la lista <T>

¿Cómo puedo hacer esto?

Gracias.

+0

Probablemente tenga más escenas para convertir DataTable en Diccionario de la lista. – Vadim

+0

@Vadim: ¿Qué te haría decir eso? –

+0

DataTable tiene filas y columnas. El diccionario representa esta estructura mucho mejor que List. – Vadim

Respuesta

18

Hay métodos de extensión Linq para DataTable.

Agregar referencia a: System.Data.DataSetExtensions.dll

A continuación se incluyen los nombres: using System.Data.DataSetExtensions

Finalmente, puede utilizar las extensiones de Linq en conjunto de datos y tablas de datos:

var matches = myDataSet.Tables.First().Where(dr=>dr.Field<int>("id") == 1); 

En .Net 2.0 aún puede agregar genérica método:

public static List<T> ConvertRowsToList<T>(DataTable input, Convert<DataRow, T> conversion) { 
    List<T> retval = new List<T>() 
    foreach(DataRow dr in input.Rows) 
     retval.Add(conversion(dr)); 

    return retval; 
} 
+1

¿Hay alguna manera fácil si se bloquea con .NET 2.0? – auujay

+0

+1 Sweeeeeet! Pero, ¿qué es la palabra clave 'Convert' aquí? ¿Te refieres a 'Convertidor'? – MoonKnight

+0

@Keith - Tiene que ser Convert ** er ** . ¿correcto? – Tohid

2

Asumiendo que su DataRow s heredan de su propio tipo, dicen MyDataRowType, esto debería funcionar:

List<MyDataRowType> list = new List<MyDataRowType>(); 

foreach(DataRow row in dataTable.Rows) 
{ 
    list.Add((MyDataRowType)row); 
} 

Esto es suponiendo, como usted ha dicho en un comentario, que está utilizando .NET 2.0 y no tiene acceso a los métodos de extensión LINQ.

+0

¿por qué no simplemente hacer una lista

+0

@Mike: dado que el OP dice que tiene una DataTable fuertemente tipada, supongo que preferiría mantener esa fuerte tipeación en sus resultados. –

+0

@ Adam, sí, me gustaría mantener el tipeo fuerte. Tengo acceso a Linq ahora en este proyecto –

37

A continuación se hace de una sola línea:

dataTable.Rows.OfType<DataRow>() 
    .Select(dr => dr.Field<MyType>(columnName)).ToList(); 

[Editar : Agregar una referencia a System.Data.DataSetExtensions a su proyecto si esto no se compila]

+17

¿Cuál es el valor de columnName aquí? – user123456

4
  1. IEnumerable<DataRow> rows = dataTable.AsEnumerable(); (System.Data .DataSetExtensions.dll)
  2. IEnumerable<DataRow> rows = dataTable.Rows.OfType<DataRow>(); (System.Core.dll)
10

Tabla de datos a la lista

#region "getobject filled object with property reconized" 

    public List<T> ConvertTo<T>(DataTable datatable) where T : new() 
    { 
     List<T> Temp = new List<T>(); 
     try 
     { 
      List<string> columnsNames = new List<string>(); 
      foreach (DataColumn DataColumn in datatable.Columns) 
       columnsNames.Add(DataColumn.ColumnName); 
      Temp = datatable.AsEnumerable().ToList().ConvertAll<T>(row => getObject<T>(row, columnsNames)); 
      return Temp; 
     } 
     catch 
     { 
      return Temp; 
     } 

    } 
    public T getObject<T>(DataRow row, List<string> columnsName) where T : new() 
    { 
     T obj = new T(); 
     try 
     { 
      string columnname = ""; 
      string value = ""; 
      PropertyInfo[] Properties; 
      Properties = typeof(T).GetProperties(); 
      foreach (PropertyInfo objProperty in Properties) 
      { 
       columnname = columnsName.Find(name => name.ToLower() == objProperty.Name.ToLower()); 
       if (!string.IsNullOrEmpty(columnname)) 
       { 
        value = row[columnname].ToString(); 
        if (!string.IsNullOrEmpty(value)) 
        { 
         if (Nullable.GetUnderlyingType(objProperty.PropertyType) != null) 
         { 
          value = row[columnname].ToString().Replace("$", "").Replace(",", ""); 
          objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(Nullable.GetUnderlyingType(objProperty.PropertyType).ToString())), null); 
         } 
         else 
         { 
          value = row[columnname].ToString().Replace("%", ""); 
          objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(objProperty.PropertyType.ToString())), null); 
         } 
        } 
       } 
      } 
      return obj; 
     } 
     catch 
     { 
      return obj; 
     } 
    } 

    #endregion 

colección IEnumerable Para dataTable

#region "New DataTable" 
    public DataTable ToDataTable<T>(IEnumerable<T> collection) 
    { 
     DataTable newDataTable = new DataTable(); 
     Type impliedType = typeof(T); 
     PropertyInfo[] _propInfo = impliedType.GetProperties(); 
     foreach (PropertyInfo pi in _propInfo) 
      newDataTable.Columns.Add(pi.Name, pi.PropertyType); 

     foreach (T item in collection) 
     { 
      DataRow newDataRow = newDataTable.NewRow(); 
      newDataRow.BeginEdit(); 
      foreach (PropertyInfo pi in _propInfo) 
       newDataRow[pi.Name] = pi.GetValue(item, null); 
      newDataRow.EndEdit(); 
      newDataTable.Rows.Add(newDataRow); 
     } 
     return newDataTable; 
    } 
+0

Se ve genial, pero ¿cómo se llama al método? –

+0

¡Este es un gran pedazo de código! Hace exactamente lo que necesitaba. Algunos años pero aún muy útil. Gracias. – Geert

+0

Me ahorró mucho tiempo ... – Abhishek

1

Crear una lista con ty pe por extender la tabla de datos con la llamada AsEnumerable.

var mylist = dt.AsEnumerable(). ToList();

¡Salud!Feliz Codificación

+0

Una tabla de datos no tiene un método AsEnumerable a menos que su solución necesite una referencia y el uso para funcionar. – johnstaveley

2

Prueba este código y ésta es la manera más fácil de convertir tabla de datos a la lista

List<DataRow> listtablename = dataTablename.AsEnumerable().ToList(); 
+0

Recibo este error; \t 'System.Data.EnumerableRowCollection ' no contiene una definición para 'ToList' y ningún método de extensión 'ToList' que acepte un primer argumento de tipo 'System.Data.EnumerableRowCollection 'se puede encontrar (¿falta una directiva using o una referencia de ensamblado?) – Salim

+0

descifrado ahora, agregado usando System.Linq; – Salim

19
List<MyType> listName = dataTableName.AsEnumerable().Select(m => new MyType() 
{ 
    ID = m.Field<string>("ID"), 
    Description = m.Field<string>("Description"), 
    Balance = m.Field<double>("Balance"), 
}).ToList() 
+0

Agradable, muy elegante. –

+0

¿Qué es ¿Puedes explicarlo por favor? No puedo entender ... –

+0

MyType es un objeto que crearías antes del código mostrado arriba con las mismas variables (ID, Descripción, Balance) –

1

favor, prueba este código:

public List<T> ConvertToList<T>(DataTable dt) 
{ 
    var columnNames = dt.Columns.Cast<DataColumn>() 
     .Select(c => c.ColumnName) 
     .ToList(); 
    var properties = typeof(T).GetProperties(); 
    return dt.AsEnumerable().Select(row => 
    { 
     var objT = Activator.CreateInstance<T>(); 
     foreach (var pro in properties) 
     { 
      if (columnNames.Contains(pro.Name)) 
       pro.SetValue(objT, row[pro.Name]); 
     } 
     return objT; 
    }).ToList(); 
} 
4

El ConvertToList método que se publica a continuación y usos la reflexión funciona perfectamente para mí. Gracias.

Hice una pequeña modificación para que funcione con las conversiones en los tipos de propiedades T.

public List<T> ConvertToList<T>(DataTable dt) 
{ 
    var columnNames = dt.Columns.Cast<DataColumn>() 
      .Select(c => c.ColumnName) 
      .ToList(); 
    var properties = typeof(T).GetProperties(); 
    return dt.AsEnumerable().Select(row => 
    { 
     var objT = Activator.CreateInstance<T>(); 
     foreach (var pro in properties) 
     { 
      if (columnNames.Contains(pro.Name)) 
      { 
       PropertyInfo pI = objT.GetType().GetProperty(pro.Name); 
       pro.SetValue(objT, row[pro.Name] == DBNull.Value ? null : Convert.ChangeType(row[pro.Name], pI.PropertyType)); 
      } 
     } 
     return objT; 
    }).ToList(); 
} 

Espero que ayude. Saludos.

+0

Gracias, Gilda. Esa función realmente funciona bien y también es rápida. – windchaser

1

puede convertir su datatable en una lista. comprobar el siguiente enlace

https://stackoverflow.com/a/35171050/1805776

public static class Helper 
{ 
    public static List<T> DataTableToList<T>(this DataTable dataTable) where T : new() 
    { 
     var dataList = new List<T>(); 

     //Define what attributes to be read from the class 
     const System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance; 

     //Read Attribute Names and Types 
     var objFieldNames = typeof(T).GetProperties(flags).Cast<System.Reflection.PropertyInfo>(). 
      Select(item => new 
      { 
       Name = item.Name, 
       Type = Nullable.GetUnderlyingType(item.PropertyType) ?? item.PropertyType 
      }).ToList(); 

     //Read Datatable column names and types 
     var dtlFieldNames = dataTable.Columns.Cast<DataColumn>(). 
      Select(item => new 
      { 
       Name = item.ColumnName, 
       Type = item.DataType 
      }).ToList(); 

     foreach (DataRow dataRow in dataTable.AsEnumerable().ToList()) 
     { 
      var classObj = new T(); 

      foreach (var dtField in dtlFieldNames) 
      { 
       System.Reflection.PropertyInfo propertyInfos = classObj.GetType().GetProperty(dtField.Name); 

       var field = objFieldNames.Find(x => x.Name == dtField.Name); 

       if (field != null) 
       { 

        if (propertyInfos.PropertyType == typeof(DateTime)) 
        { 
         propertyInfos.SetValue 
         (classObj, convertToDateTime(dataRow[dtField.Name]), null); 
        } 
        else if (propertyInfos.PropertyType == typeof(Nullable<DateTime>)) 
        { 
         propertyInfos.SetValue 
         (classObj, convertToDateTime(dataRow[dtField.Name]), null); 
        } 
        else if (propertyInfos.PropertyType == typeof(int)) 
        { 
         propertyInfos.SetValue 
         (classObj, ConvertToInt(dataRow[dtField.Name]), null); 
        } 
        else if (propertyInfos.PropertyType == typeof(long)) 
        { 
         propertyInfos.SetValue 
         (classObj, ConvertToLong(dataRow[dtField.Name]), null); 
        } 
        else if (propertyInfos.PropertyType == typeof(decimal)) 
        { 
         propertyInfos.SetValue 
         (classObj, ConvertToDecimal(dataRow[dtField.Name]), null); 
        } 
        else if (propertyInfos.PropertyType == typeof(String)) 
        { 
         if (dataRow[dtField.Name].GetType() == typeof(DateTime)) 
         { 
          propertyInfos.SetValue 
          (classObj, ConvertToDateString(dataRow[dtField.Name]), null); 
         } 
         else 
         { 
          propertyInfos.SetValue 
          (classObj, ConvertToString(dataRow[dtField.Name]), null); 
         } 
        } 
        else 
        { 

         propertyInfos.SetValue 
          (classObj, Convert.ChangeType(dataRow[dtField.Name], propertyInfos.PropertyType), null); 

        } 
       } 
      } 
      dataList.Add(classObj); 
     } 
     return dataList; 
    } 

    private static string ConvertToDateString(object date) 
    { 
     if (date == null) 
      return string.Empty; 

     return date == null ? string.Empty : Convert.ToDateTime(date).ConvertDate(); 
    } 

    private static string ConvertToString(object value) 
    { 
     return Convert.ToString(ReturnEmptyIfNull(value)); 
    } 

    private static int ConvertToInt(object value) 
    { 
     return Convert.ToInt32(ReturnZeroIfNull(value)); 
    } 

    private static long ConvertToLong(object value) 
    { 
     return Convert.ToInt64(ReturnZeroIfNull(value)); 
    } 

    private static decimal ConvertToDecimal(object value) 
    { 
     return Convert.ToDecimal(ReturnZeroIfNull(value)); 
    } 

    private static DateTime convertToDateTime(object date) 
    { 
     return Convert.ToDateTime(ReturnDateTimeMinIfNull(date)); 
    } 

    public static string ConvertDate(this DateTime datetTime, bool excludeHoursAndMinutes = false) 
    { 
     if (datetTime != DateTime.MinValue) 
     { 
      if (excludeHoursAndMinutes) 
       return datetTime.ToString("yyyy-MM-dd"); 
      return datetTime.ToString("yyyy-MM-dd HH:mm:ss.fff"); 
     } 
     return null; 
    } 
    public static object ReturnEmptyIfNull(this object value) 
    { 
     if (value == DBNull.Value) 
      return string.Empty; 
     if (value == null) 
      return string.Empty; 
     return value; 
    } 
    public static object ReturnZeroIfNull(this object value) 
    { 
     if (value == DBNull.Value) 
      return 0; 
     if (value == null) 
      return 0; 
     return value; 
    } 
    public static object ReturnDateTimeMinIfNull(this object value) 
    { 
     if (value == DBNull.Value) 
      return DateTime.MinValue; 
     if (value == null) 
      return DateTime.MinValue; 
     return value; 
    } 
} 
1

Hay un pequeño example que puede utilizar

  DataTable dt = GetCustomersDataTable(null);    

      IEnumerable<SelectListItem> lstCustomer = dt.AsEnumerable().Select(x => new SelectListItem() 
      { 
       Value = x.Field<string>("CustomerId"), 
       Text = x.Field<string>("CustomerDescription") 
      }).ToList(); 

      return lstCustomer; 
Cuestiones relacionadas