简体   繁体   English

将DataTable转换为通用List?

[英]Convert DataTable to generic List?

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

Thats the only thing we can think of right now is that we must be doing something where we need to Garbage collect Ourselves? 那就是我们现在唯一能想到的就是我们必须做一些我们需要垃圾收集的事情吗?

Thoughts? 思考?

Why we think there might be a leak?: 为什么我们认为可能存在泄漏?:

We are getting Out of Memory Errors. 我们正在失去内存错误。 If a Page does not require business logic to use this type of conversion, the II6 process does not grow, but when we hit a page that uses it, it grows. 如果一个页面不需要业务逻辑来使用这种类型的转换,那么II6进程就不会增长,但是当我们点击一​​个使用它的页面时,它就会增长。

We are currently getting ANTS Profiler to give us more details. 我们目前正在获取ANTS Profiler以向我们提供更多详细信息。

That won't be an actual leak , but it could be stressing things unnecessarily... 这不会是一个实际的泄漏 ,但它可能会不必要地强调事情......

How many rows are you working over? 你工作了多少行? Note that reflection is a pain, and that every call to things like GetCustomAttributes can return a new array (so you want to do that once, not once per-property-per-row). 请注意,反射是一种痛苦,每次调用GetCustomAttributes东西都可以返回一个新数组(所以你想要这样做一次,而不是每行每个属性一次)。

Personally, I'd pre-construct the work I intend to do... something like below. 就个人而言,我预先构建了我打算做的工作......如下所示。

Note that if I was doing this lots, I'd either switch to HyperDescriptor , or if .NET 3.5 was an option, maybe a compiled Expression. 请注意,如果我这样做,我要么切换到HyperDescriptor ,要么.NET 3.5是一个选项,可能是一个已编译的表达式。 Since DataTable isn't strongly typed, HyperDescriptor would be a logical next step (for performance) after the below... 由于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;        
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM