Convert DataTable to List

后端 未结 14 1761
挽巷
挽巷 2020-12-04 12:09

I have an strongly typed DataTable of type MyType, I\'d like convert it in a List.

How can I do this ?

Thanks.

相关标签:
14条回答
  • 2020-12-04 12:37
    1. IEnumerable<DataRow> rows = dataTable.AsEnumerable(); (System.Data.DataSetExtensions.dll)
    2. IEnumerable<DataRow> rows = dataTable.Rows.OfType<DataRow>(); (System.Core.dll)
    0 讨论(0)
  • 2020-12-04 12:41

    The method ConvertToList that is posted below and uses reflection works perfectly for me. Thanks.

    I made a slight modification to make it work with conversions on the T property types.

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

    Hope it helps. Regards.

    0 讨论(0)
  • 2020-12-04 12:43

    you can convert your datatable to list. check the following link

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-04 12:46

    Assuming your DataRows inherit from your own type, say MyDataRowType, this should work:

    List<MyDataRowType> list = new List<MyDataRowType>();
    
    foreach(DataRow row in dataTable.Rows)
    {
        list.Add((MyDataRowType)row);
    }
    

    This is assuming, as you said in a comment, that you're using .NET 2.0 and don't have access to the LINQ extension methods.

    0 讨论(0)
  • 2020-12-04 12:47

    There are Linq extension methods for DataTable.

    Add reference to: System.Data.DataSetExtensions.dll

    Then include the namespace: using System.Data.DataSetExtensions

    Finally you can use Linq extensions on DataSet and DataTables:

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

    On .Net 2.0 you can still add generic method:

    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;
    }
    
    0 讨论(0)
  • 2020-12-04 12:49

    The following does it in a single line:

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

    [Edit: Add a reference to System.Data.DataSetExtensions to your project if this does not compile]

    0 讨论(0)
提交回复
热议问题