2010-02-17 13 views
5

tengo una duda, en algún momento me hizo esta conversión de DataTable a List<T>:DataTable Convertir a la lista <T>

List<EDog> lstDogs = (from drRow in dsDogs.Tables[0].AsEnumerable() 
         select new EDog() 
         { 
          intIdDog = drRow.Field<int>("IdDog"), 
          intIdOwner = drRow.Field<int?>("IdOwner"), 
          intAge = drRow.Field<int>("Age"), 
          strName = drRow.Field<string>("Name") 
         }).ToList(); 

Esto funcionó bien, pero ahora estoy pensando en hacerlo genérico, por lo que cualquier tipo de DataSet se podría convertir a una lista fuertemente tipada.

¿Cómo podría hacerlo genérico? tal vez un delegado que rodea esta parte y crea el objeto?

new EDog() 
{ 
    intIdDog = drRow.Field<int>("IdDog"), 
    intIdOwner = drRow.Field<int?>("IdOwner"), 
    intAge = drRow.Field<int>("Age"), 
    strName = drRow.Field<string>("Name") 
} 

lo intenté, pero sale un error:

select (lambda) expected.... 

Cualquier sugerencia?

La razón por la que necesito esto es porque cada DataRow del resultado, necesita ser convertido a una Entidad para una mejor manipulación.

+0

Qué lenguaje es esto? –

+0

C# parece ... –

+1

Cómo convertir una DataTable en una lista genérica: http://stackoverflow.com/questions/208532/how-do-you-convert-a-datatable-into-a- generic-list – sashaeve

Respuesta

6

¿Es algo así como lo que estás buscando?

public static List<T> ConvertDS<T>(DataSet ds, Converter<DataRow, T> converter) 
{ 
    return 
     (from row in ds.Tables[0].AsEnumerable() 
     select converter(row)).ToList(); 
} 
+0

Exactamente, gracias, eso es lo que realmente hice, y luego hice el recíproco en el método de conversión fila por fila. Gracias por ti – lidermin

1

No se presta para convertirse fácilmente, puede hacerlo, pero probablemente no ahorrará mucho trabajo.

Considere el conocimiento intrínseco en su muestra de código: conoce el tipo y el nombre de cada columna en el DataTable y el tipo y nombre de la propiedad a la que se asigna en el tipo de salida. La alternativa sería conocer el tipo y el índice de cada columna (sustituyendo el nombre por el índice). En ambos casos, necesitaría definir una asignación para contener esa información.

La alternativa sería construir un convertidor basado en convenciones; en otras palabras, sus nombres de columna DataTable y sus propiedades de destino necesitarían ser nombradas de forma consistente y desviarse de esa convención daría como resultado la conversión fallada.

10

Ok, vamos a tener un poco de diversión:

public static class DataTableExtensions 
{ 
    public static List<T> ToGenericList<T>(this DataTable datatable, Func<DataRow, T> converter) 
    { 
     return (from row in datatable.AsEnumerable() 
       select converter(row)).ToList(); 
    } 
} 

class EDog 
{ 
    private int intIdDog; 
    private int intIdOwner; 
    private int intAge; 
    private string strName; 

    ... 

    public static EDog Converter(DataRow row) 
    { 
     return new EDog 
         { 
          intIdDog = (int)row["IdDog"], 
          intIdOwner = (int)row["IdOwner"], 
          intAge = (int)row["Age"], 
          strName = row["Name"] as string 
         }; 
    } 
} 

Uso:

List<EDog> dogs = dsDogs.Tables[0].ToGenericList<EDog>(EDog.Converter); 

Pero no es lo suficientemente divertido, ¿verdad? ¿Qué hay de esto:

class DataRowKeyAttribute : Attribute 
{ 
    private readonly string _Key; 

    public string Key 
    { 
     get { return _Key; } 
    } 

    public DataRowKeyAttribute(string key) 
    { 
     _Key = key; 
    } 
} 


static class DataTableExtensions 
{ 
    public static List<T> ToGenericList<T>(this DataTable datatable) where T : new() 
    { 
     return (from row in datatable.AsEnumerable() 
       select Convert<T>(row)).ToList(); 
    } 

    private static T Convert<T>(DataRow row) where T : new() 
    { 
     var result = new T(); 

     var type = result.GetType(); 

     foreach (var fieldInfo in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)) 
     { 
      var dataRowKeyAttribute = fieldInfo.GetCustomAttributes(typeof (DataRowKeyAttribute), true).FirstOrDefault() as DataRowKeyAttribute; 
      if (dataRowKeyAttribute != null) 
      { 
       fieldInfo.SetValue(result, row[dataRowKeyAttribute.Key]); 
      } 
     } 

     return result; 
    } 
} 

class EDog 
{ 
    [DataRowKey("IdDog")] 
    private int intIdDog; 
    [DataRowKey("IdOwner")] 
    private int intIdOwner; 
    [DataRowKey("Age")] 
    private int intAge; 
    [DataRowKey("Name")] 
    private string strName; 

    ... 
} 

Uso:

List<EDog> dogs = dsDogs.Tables[0].ToGenericList<EDog>(); 

Y si usted quiere tener verdadera diversión, añadir el control de errores, considere el almacenamiento en caché los datos de reflexión para mejorar el rendimiento y modificar campos de propiedades.

-1

que era capaz de hacerlo en una sola línea de código: dt es la DataTable

List<DataRow> alist = new dt.AsEnumerable().ToList(); 
+0

Esto no responde la pregunta. El requisito era producir una lista de objetos tipados (EDog en este caso) y no una lista de DataRow. – Andreas

Cuestiones relacionadas