将 DataTable 转换为通用列表?

Posted

技术标签:

【中文标题】将 DataTable 转换为通用列表?【英文标题】:Convert DataTable to generic List? 【发布时间】:2010-10-07 09:59:41 【问题描述】:
    public static IList<T> ConvertTo<T>(DataTable table)
    
        if (table == null)
        
            return null;
        

        List<DataRow> rows = new List<DataRow>();

        foreach (DataRow row in table.Rows)
        
            rows.Add(row);
        

        return ConvertTo<T>(rows);
    

    public static T ConvertItem<T>(DataTable table)
    
        T obj = default(T);
        if (table != null && table.Rows.Count > 0)
        
            obj = CreateItem<T>(table.Rows[0]);
        
        return obj;
    


    public static T CreateItem<T>(DataRow row)
    
        T obj = default(T);
        if (row != null)
        
            obj = Activator.CreateInstance<T>();
            Type entityType = typeof(T);
            PropertyInfo[] properties = entityType.GetProperties();

            for (int i = 0; i < properties.Length; i++)
            
                object[] customAttributes = properties[i].GetCustomAttributes(typeof(ColumnAttributes), false);
                ColumnAttributes dataField = null;
                if (null != customAttributes && customAttributes.Length > 0 && null != (dataField = customAttributes[0] as ColumnAttributes))
                
                    if (row.Table.Columns.Contains(dataField.FieldName) && !row[dataField.FieldName].GetType().FullName.Equals("System.DBNull"))
                    
                        properties[i].SetValue(obj, row[dataField.FieldName], null);
                    
                
            
        
        return obj;
    

我们现在唯一能想到的就是我们必须做一些我们需要收集自己的垃圾的事情?

想法?

为什么我们认为可能存在泄漏?:

我们遇到内存不足错误。如果一个页面不需要业务逻辑来使用这种类型的转换,那么 II6 流程就不会增长,但是当我们点击一​​个使用它的页面时,它就会增长。

我们目前正在获取 ANTS Profiler 以提供更多详细信息。

【问题讨论】:

你有什么泄漏证据? 问题到底出在哪里? 我的第一个想法是你永远不应该为自己调用 GC.Collect。根据您提供的信息,我没有看到任何真正的问题。您是否尝试过使用分析器进行检查? 有一种通用方法可以将您的 DT 转换为通用列表。请参阅以下链接:dotnetobject.com/… 【参考方案1】:

这不会是真正的泄漏,但它可能会造成不必要的压力......

您正在处理多少行? 请注意,反射很痛苦,每次调用 GetCustomAttributes 之类的东西都可以返回一个新数组(所以你想这样做一次,而不是每个属性每行一次)。

就个人而言,我会预先构建我打算做的工作......如下所示。

请注意,如果我经常这样做,我会切换到HyperDescriptor,或者如果.NET 3.5 是一个选项,也许是编译的表达式。由于DataTable 不是强类型,HyperDescriptor 将是下面的逻辑下一步(对于性能)...

sealed class Tuple<T1, T2>

    public Tuple() 
    public Tuple(T1 value1, T2 value2) Value1 = value1; Value2 = value2;
    public T1 Value1 get;set;
    public T2 Value2 get;set;

public static List<T> Convert<T>(DataTable table)
    where T : class, new()

    List<Tuple<DataColumn, PropertyInfo>> map =
        new List<Tuple<DataColumn,PropertyInfo>>();

    foreach(PropertyInfo pi in typeof(T).GetProperties())
    
        ColumnAttribute col = (ColumnAttribute)
            Attribute.GetCustomAttribute(pi, typeof(ColumnAttribute));
        if(col == null) continue;
        if(table.Columns.Contains(col.FieldName))
        
            map.Add(new Tuple<DataColumn,PropertyInfo>(
                table.Columns[col.FieldName], pi));
        
    

    List<T> list = new List<T>(table.Rows.Count);
    foreach(DataRow row in table.Rows)
    
        if(row == null)
        
            list.Add(null);
            continue;
        
        T item = new T();
        foreach(Tuple<DataColumn,PropertyInfo> pair in map) 
            object value = row[pair.Value1];
            if(value is DBNull) value = null;
            pair.Value2.SetValue(item, value, null);
        
        list.Add(item);
    
    return list;        

【讨论】:

我同意马克的观点。您的代码既慢又相当复杂!此外,您应该检查属性的类型,以免尝试将 int 的值设置为字符串值等等。

以上是关于将 DataTable 转换为通用列表?的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中将 DataTable 转换为通用列表

.NET - 将通用集合转换为 DataTable

使用反射将数据读取器转换为列表的最快方法

在c#中遍历通用类型列表

C# - 将 DataReader 转换为 DataTable

将DataTable转换成CSV文件