C# 将数据表转换为通用列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/545328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert DataTable to generic List?
提问by TimLeung
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.
我们遇到内存不足错误。如果一个 Page 不需要业务逻辑来使用这种类型的转换,那么 II6 进程不会增长,但是当我们点击一个使用它的页面时,它会增长。
We are currently getting ANTS Profiler to give us more details.
我们目前正在使用 ANTS Profiler 为我们提供更多详细信息。
采纳答案by Marc Gravell
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. Since DataTable
isn't strongly typed, HyperDescriptor
would be a logical next step (for performance) after the below...
请注意,如果我做了这么多,我要么切换到HyperDescriptor,或者如果 .NET 3.5 是一个选项,可能是一个编译的 Expression。由于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;
}