2009-09-15 6 views
36

J'ai un DataTable fortement typé de type MyType, je voudrais le convertir en List<MyType>.Convertir DataTable à la liste <T>

Comment est-ce que je peux faire ceci?

Merci.

+0

Il fait probablement plus de scènes à convertir DataTable dans le dictionnaire de liste. – Vadim

+0

@Vadim: Qu'est-ce qui vous ferait dire ça? –

+0

DataTable a des lignes et des colonnes. Le dictionnaire représente beaucoup mieux cette structure que List. – Vadim

Répondre

18

Il existe des méthodes d'extension Linq pour DataTable.

Ajouter référence à: System.Data.DataSetExtensions.dll

comprennent alors l'espace de noms: using System.Data.DataSetExtensions

Enfin, vous pouvez utiliser des extensions Linq sur DataSet et DataTable:

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

.Net 2.0 vous pouvez toujours ajouter générique méthode:

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

Y at-il un moyen facile si coincé avec .NET 2.0? – auujay

+0

+1 Sweeeeeet! Mais quel est le mot clé 'Convert' ici? Voulez-vous dire 'Converter'? – MoonKnight

+0

@Keith - Il doit être Convert ** er ** . correct? – Tohid

2

En supposant que votre DataRow s héritent de votre propre type, disent MyDataRowType, cela devrait fonctionner:

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

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

Cela suppose, comme vous l'avez dit dans un commentaire, que vous utilisez .NET 2.0 et n'ont pas accès aux méthodes d'extension LINQ.

+0

pourquoi ne pas simplement faire une liste

+0

@Mike: Puisque l'OP dit qu'il a un DataTable fortement typé, je suppose qu'il préférerait garder ce typage fort dans ses résultats. –

+0

@Adam, oui je voudrais garder le typage fort. J'ai maintenant accès à Linq dans ce projet –

37

qui suit le fait d'une seule ligne:

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

[Modifier : Ajouter une référence à System.Data.DataSetExtensions à votre projet si cela ne compile pas]

+17

Quelle est la valeur de columnName ici? – user123456

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

Tableau de données Liste

#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 

collection IEnumerable 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

Ça a l'air génial, mais comment appelez-vous la méthode? –

+0

C'est un super morceau de code !!! Il fait exactement ce dont j'avais besoin. Quelques années mais toujours très utile. Merci. – Geert

+0

Il m'a sauvé beaucoup de temps ... – Abhishek

1

Créer une liste ty pe par extension de la date avec l'appel AsEnumerable.

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

À la vôtre !!Bonne programmation

+0

Un DataTable n'a pas de méthode AsEnumerable à moins que votre solution nécessite une référence et que vous l'utilisiez pour fonctionner. – johnstaveley

2

Essayez ce code, ce qui est plus simple de convertir datatable à la liste

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

Je reçois cette erreur; \t 'System.Data.EnumerableRowCollection ' ne contient pas de définition pour 'ToList' et aucune méthode d'extension 'ToList' acceptant un premier argument de type 'System.Data.EnumerableRowCollection 'peut être trouvé (manque-t-il une directive using ou une référence d'assembly?) – Salim

+0

trouvé maintenant, ajouté en utilisant 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

Nice, très élégant. –

+0

qu'est-ce que pouvez-vous expliquer s'il vous plaît? Je ne comprends pas .. –

+0

MyType est un objet que vous créer avant le code ci-dessus avec les mêmes variables (ID, Description, Balance) –

1

s'il vous plaît essayer ce code:

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

La méthode ConvertToList qui est affiché ci-dessous et utilisations la réflexion fonctionne parfaitement pour moi. Merci.

J'ai fait une légère modification pour le faire fonctionner avec des conversions sur les types de propriétés 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(); 
} 

Espérons que cela aide. Cordialement.

+0

Merci, Gilda. Cette fonction fonctionne vraiment bien et elle est également rapide. – windchaser

1

vous pouvez convertir votre datatable en liste. consultez le lien suivant

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

Il y a un peu example que vous pouvez utiliser

  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; 
Questions connexes