2010-02-17 7 views
5

J'ai un doute, parfois je fait cette conversion DataTable-List<T>:DataTable liste Convertir <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(); 

Cela a bien fonctionné, mais maintenant je pense à le faire générique, de sorte que tout type de DataSet pourrait être converti en une liste fortement typée.

Comment pourrais-je le rendre générique? peut-être un délégué entourant cette partie et créant l'objet?

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

Je l'ai essayé, mais obtenir une erreur:

select (lambda) expected.... 

Toute suggestion?

La raison pour laquelle j'en ai besoin est que chaque DataRow du résultat doit être converti en Entité pour une meilleure manipulation.

+0

Quelle langue est-ce? –

+0

C# il semble ...... –

+1

Comment convertir un DataTable en une liste générique: http://stackoverflow.com/questions/208532/how-do-you-convert-a-datatable-into-a- generic-list – sashaeve

Répondre

6

Quelque chose comme ça est ce que vous cherchez?

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

Exactement, merci, c'est ce que j'ai réellement fait, et puis j'ai fait l'inverse sur la méthode de conversion rangée par rangée. Merci pour vous – lidermin

1

Il ne se prêtera pas facilement à être converti, vous pouvez le faire mais cela ne sauvera probablement pas beaucoup de travail. Pensez à la connaissance intrinsèque de votre exemple de code: vous connaissez le type et le nom de chaque colonne du DataTable et le type et le nom de la propriété à laquelle elle correspond dans le type de sortie. L'alternative serait de connaître le type et l'index de chaque colonne (en substituant le nom à l'index). Dans les deux cas, vous devrez définir un mappage pour contenir cette information. L'alternative serait de construire un convertisseur basé sur une convention - en d'autres termes, vos noms de colonnes DataTable et leurs propriétés cibles devraient être nommés de façon cohérente et s'écarter de cette convention entraînerait l'échec de la conversion.

10

Ok, nous allons avoir du plaisir:

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

Utilisation:

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

Mais il n'y a pas assez amusant, non? Qu'en est-ce:

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; 

    ... 
} 

Utilisation:

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

Et si vous voulez avoir du plaisir réel, ajouter la gestion des erreurs, envisager la mise en cache des données de réflexion pour améliorer les performances et l'évolution des champs de propriétés.

-1

j'ai pu le faire en une seule ligne de code: dt est le DataTable

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

Cela ne répond pas à la question. L'exigence était de produire une liste d'objets typés (EDog dans ce cas) et non une liste de DataRow. – Andreas

Questions connexes