将通用的List/Enumerable转换为DataTable?

312

我有几个返回不同泛型列表的方法。

在 .net 中是否存在将任何列表转换为数据表的类静态方法或其他方法?我唯一能想象的就是使用反射来实现这一点。

如果我有以下内容:

List<Whatever> whatever = new List<Whatever>();

(当然,以下代码不能正常工作,但我希望有这个可能性:

DataTable dt = (DataTable) whatever;

2
当然,一个好问题是“为什么?” - 当List<T>在许多情况下比DataTable更好时;-p 我想每个人都有自己的选择... - Marc Gravell
1
我认为这个问题可能是这个问题的重复:https://dev59.com/RnRB5IYBdhLWcg3wxZxK 它甚至有一个非常相似的答案。 :-) - mezoid
2
@MarcGravell:我的“为什么?”是关于List<T>操作(遍历列和行)。我正在尝试从List<T>制作一个数据透视表,并通过反射访问属性,但这很麻烦。我做错了吗? - Eduardo Molteni
1
@Eduardo,有许多工具可以消除反射痛苦,例如FastMember。也可能DataTable对于特定情况非常有用-这完全取决于上下文。也许最大的问题是人们仅仅因为它存在就使用DataTable来存储所有数据,而没有花时间考虑选项和场景。 - Marc Gravell
如果你只是想要进行数据透视,为什么不使用linqLib http://linqlib.codeplex.com/ 呢?它实现了几乎所有你能想到的IEnumerable操作。 - Pedro.The.Kid
显示剩余4条评论
28个回答

1
要将通用列表转换为数据表,您可以使用 DataTableGenerator
该库使您可以将列表转换为具有多功能的数据表,例如:
  • 翻译数据表头
  • 指定一些要显示的列

请注意保留HTML标签。

1
如果您正在使用VB.NET,那么这个类可以完成任务。
Imports System.Reflection
''' <summary>
''' Convert any List(Of T) to a DataTable with correct column types and converts Nullable Type values to DBNull
''' </summary>

Public Class ConvertListToDataset

    Public Function ListToDataset(Of T)(ByVal list As IList(Of T)) As DataTable

        Dim dt As New DataTable()
        '/* Create the DataTable columns */
        For Each pi As PropertyInfo In GetType(T).GetProperties()
            If pi.PropertyType.IsValueType Then
                Debug.Print(pi.Name)
            End If
            If IsNothing(Nullable.GetUnderlyingType(pi.PropertyType)) Then
                dt.Columns.Add(pi.Name, pi.PropertyType)
            Else
                dt.Columns.Add(pi.Name, Nullable.GetUnderlyingType(pi.PropertyType))
            End If
        Next

        '/* Populate the DataTable with the values in the Items in List */
        For Each item As T In list
            Dim dr As DataRow = dt.NewRow()
            For Each pi As PropertyInfo In GetType(T).GetProperties()
                dr(pi.Name) = IIf(IsNothing(pi.GetValue(item)), DBNull.Value, pi.GetValue(item))
            Next
            dt.Rows.Add(dr)
        Next
        Return dt

    End Function

End Class

0
这是一个简单的控制台应用程序,用于将列表转换为数据表。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.ComponentModel;

namespace ConvertListToDataTable
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            List<MyObject> list = new List<MyObject>();
            for (int i = 0; i < 5; i++)
            {
                list.Add(new MyObject { Sno = i, Name = i.ToString() + "-KarthiK", Dat = DateTime.Now.AddSeconds(i) });
            }

            DataTable dt = ConvertListToDataTable(list);
            foreach (DataRow row in dt.Rows)
            {
                Console.WriteLine();
                for (int x = 0; x < dt.Columns.Count; x++)
                {
                    Console.Write(row[x].ToString() + " ");
                }
            }
            Console.ReadLine();
        }

        public class MyObject
        {
            public int Sno { get; set; }
            public string Name { get; set; }
            public DateTime Dat { get; set; }
        }

        public static DataTable ConvertListToDataTable<T>(this List<T> iList)
        {
            DataTable dataTable = new DataTable();
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
            for (int i = 0; i < props.Count; i++)
            {
                PropertyDescriptor propertyDescriptor = props[i];
                Type type = propertyDescriptor.PropertyType;

                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                    type = Nullable.GetUnderlyingType(type);

                dataTable.Columns.Add(propertyDescriptor.Name, type);
            }
            object[] values = new object[props.Count];
            foreach (T iListItem in iList)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = props[i].GetValue(iListItem);
                }
                dataTable.Rows.Add(values);
            }
            return dataTable;
        }
    }
}

0
List<object> Basket;

string json = JsonConvert.SerializeObject(Basket, Formatting.Indented);
DataTable dtUsingMethod = Business.GetJSONToDataTableUsingNewtonSoftDll(json);



public static DataTable GetJSONToDataTableUsingNewtonSoftDll(string JSONData)
{
    DataTable dt = (DataTable)JsonConvert.DeserializeObject(JSONData, (typeof(DataTable)));
    return dt;
}

3
你能否进一步解释一下你的代码是做什么的,以及它是否需要任何依赖项(比如NewtonSoft)? - Frankich

0

这里又有一个加入列表:Cinchoo ETL - 一个将可枚举对象转换为数据表格的开源库。

List<Whatever> whatever = new List<Whatever>();
var dt = whatever.AsDataTable();

声明:本库的作者是我。


0

我认为它更方便易用。

   List<Whatever> _lobj= new List<Whatever>(); 
    var json = JsonConvert.SerializeObject(_lobj);
                DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));

0
 Dim counties As New List(Of County)
 Dim dtCounties As DataTable
 dtCounties = _combinedRefRepository.Get_Counties()
 If dtCounties.Rows.Count <> 0 Then
    For Each row As DataRow In dtCounties.Rows
      Dim county As New County
      county.CountyId = row.Item(0).ToString()
      county.CountyName = row.Item(1).ToString().ToUpper()
      counties.Add(county)
    Next
    dtCounties.Dispose()
 End If

0
如果您想使用反射并设置列顺序/仅包含某些列/排除某些列,请尝试以下方法:
        private static DataTable ConvertToDataTable<T>(IList<T> data, string[] fieldsToInclude = null,
string[] fieldsToExclude = null)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable();
        foreach (PropertyDescriptor prop in properties)
        {
            if ((fieldsToInclude != null && !fieldsToInclude.Contains(prop.Name)) ||
                (fieldsToExclude != null && fieldsToExclude.Contains(prop.Name)))
                continue;
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        }

        foreach (T item in data)
        {
            var atLeastOnePropertyExists = false;
            DataRow row = table.NewRow();
            foreach (PropertyDescriptor prop in properties)
            {

                if ((fieldsToInclude != null && !fieldsToInclude.Contains(prop.Name)) ||
(fieldsToExclude != null && fieldsToExclude.Contains(prop.Name)))
                    continue;

                row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                atLeastOnePropertyExists = true;
            }

            if(atLeastOnePropertyExists) table.Rows.Add(row);
        }


        if (fieldsToInclude != null)
            SetColumnsOrder(table, fieldsToInclude);

        return table;

    }

    private static void SetColumnsOrder(DataTable table, params String[] columnNames)
    {
        int columnIndex = 0;
        foreach (var columnName in columnNames)
        {
            table.Columns[columnName].SetOrdinal(columnIndex);
            columnIndex++;
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接