2009-09-15 2 views
36

У меня есть строго типизированный DataTable типа MyType, я бы хотел преобразовать его в List<MyType>.Преобразование DataTable в список <T>

Как это сделать?

Спасибо.

+0

Это, вероятно, делает больше сцен для преобразования объекта DataTable в словарь, чем список. – Vadim

+0

@ Вадим: Что бы вы так сказали? –

+0

DataTable имеет строки и столбцы. Словарь представляет эту структуру намного лучше, чем List. – Vadim

ответ

18

Существуют методы расширения Linq для DataTable.

Добавить ссылку на: System.Data.DataSetExtensions.dll

Затем включите пространство имен: using System.Data.DataSetExtensions

Наконец, вы можете использовать Linq расширения на DataSet и DataTables:

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

На .Net 2.0 вы можете добавить родовое метод:

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

Есть ли простой способ, если вы используете .NET 2.0? – auujay

+0

+1 Sweeeeeet! Но каково здесь ключевое слово Convert? Вы имеете в виду «Конвертер»? – MoonKnight

+0

@ Keith - Он должен быть преобразован ** er ** . верный? – Tohid

2

Если предположить, что ваши DataRow s наследовать от вашего собственного типа, скажем MyDataRowType, это должно работать:

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

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

Это предполагает, что, как вы сказали в комментариях, что вы используете .NET 2.0 и не имеют доступа к методам расширения LINQ.

+0

почему бы не просто составить список

+0

@Mike: Поскольку OP говорит, что у него сильно типизированный DataTable, я бы предположил, что он предпочел бы сохранить эту сильную типизацию в своих результатах. –

+0

@ Адам, да, я бы хотел сохранить сильную типизацию. У меня есть доступ к Linq сейчас в этом проекте –

37

Следующие делает это в одной строке:

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

[Edit: Добавить ссылку на System.Data.DataSetExtensions ваш проект, если это не компилирует]

+17

Что такое значение columnName? – user123456

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

таблица данных в список

#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 

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

Выглядит отлично, но как вы называете метод? –

+0

Это отличный кусок кода !!! Он делает именно то, что мне нужно. Несколько лет, но все же очень полезно. Благодарю. – Geert

+0

Это сэкономило много времени ... – Abhishek

1

Создать список с ти pe, увеличивая число данных с помощью вызова AsEnumerable.

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

Cheers !!Счастливый Coding

+0

DataTable не имеет метода AsEnumerable, если вашему решению не требуется ссылка и использование для работы. – johnstaveley

2

Попробуйте этот код и это самый простой способ конвертировать DataTable в список

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

Я получаю эту ошибку; \t «System.Data.EnumerableRowCollection » не содержит определения для «ToList» и никакого метода расширения «ToList», принимающего первый аргумент типа «System.Data.EnumerableRowCollection '(вам не хватает директивы using или ссылки на сборку?) – Salim

+0

теперь вычислен, добавлен с использованием 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

Ницца, очень элегантный. –

+0

Что такое Можно ли объяснить это пожалуйста ?? Я не могу понять .. –

+0

MyType - это объект, который вы создали бы перед кодом, показанным выше, с теми же переменными (ID, Описание, Баланс) –

1

пожалуйста попробуйте этот код:

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

метод ConvertToList, который размещен ниже, и использует отражение прекрасно работает для меня. Благодарю.

Я сделал небольшую модификацию, чтобы заставить ее работать с преобразованиями в свойствах типа 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(); 
} 

Надеюсь, что это поможет. С уважением.

+0

Спасибо, Гильда. Эта функция действительно работает хорошо, и она также быстро прекращается. – windchaser

1

Вы можете конвертировать данные в список. проверьте ссылку

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

Существует немного example, что вы можете использовать

  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; 
Смежные вопросы