将 DataTable 转换为 List<T>

Posted

技术标签:

【中文标题】将 DataTable 转换为 List<T>【英文标题】:Convert DataTable to List<T> 【发布时间】:2011-01-17 21:54:57 【问题描述】:

我有一个疑问,有时我从DataTable 转换为List&lt;T&gt;

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

这工作得很好,但现在我正在考虑将其通用化,以便任何类型的 DataSet 都可以转换为强类型列表。

我怎样才能使它通用?也许是围绕这部分并创建对象的委托?

new EDog()

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

我试过了,但是报错:

select (lambda) expected....

有什么建议吗?

我需要这个的原因是因为结果的每个 DataRow 都需要转换为实体以便更好地操作。

【问题讨论】:

如何将 DataTable 转换为通用列表:***.com/questions/208532/… 谢谢,但我们的想法是不要使用 foreach 语句。 或:***.com/questions/545328/… 【参考方案1】:

好吧,让我们玩得开心:

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
                        ;
    

用法:

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

但是没有足够的乐趣,对吧?这个呢:

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;

    ... 

用法:

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

如果您想获得真正的乐趣,请添加错误处理,考虑缓存反射数据以提高性能并将字段更改为属性。

【讨论】:

【参考方案2】:

您正在寻找类似的东西吗?

public static List<T> ConvertDS<T>(DataSet ds, Converter<DataRow, T> converter)

    return
        (from row in ds.Tables[0].AsEnumerable()
         select converter(row)).ToList();

【讨论】:

正是,谢谢,这就是我实际所做的,然后我在转换器方法上逐行进行了转换。谢谢你【参考方案3】:

它不会轻易转换,你可以做到,但它可能不会节省太多工作。

想想你的代码示例中的内在知识:你知道DataTable 中每一列的类型和名称,以及它在输出类型中映射到的属性的类型和名称。另一种方法是知道每列的类型和索引(用名称代替索引)。在这两种情况下,您都需要定义一个映射来包含该信息。

替代方法是构建一个基于约定的转换器 - 换句话说,您的 DataTable 列名称及其目标属性需要一致命名,偏离该约定会导致转换失败。

【讨论】:

【参考方案4】:

我能够在一行代码中做到这一点: dt 是数据表

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

【讨论】:

这没有回答问题。要求是生成类型化对象列表(在本例中为 EDog),而不是 DataRow 列表。

以上是关于将 DataTable 转换为 List<T>的主要内容,如果未能解决你的问题,请参考以下文章

将list转换为datatable

DataTable转换为List

如何将DataTable转换成List<T>

DataTable转换为其他对象

将list转换为datatable的方法

将 DataTable 转换为 IEnumerable<T>