.net 将datatable转换为通用列表的最快方法
我有一个返回datatable的数据层选择方法。它是从业务层方法调用的,然后该方法将返回一个强类型的泛型列表 我想做的与这个问题非常相似(但不相同):.net 将datatable转换为通用列表的最快方法,.net,.net-2.0,datatable,n-tier-architecture,.net,.net 2.0,Datatable,N Tier Architecture,我有一个返回datatable的数据层选择方法。它是从业务层方法调用的,然后该方法将返回一个强类型的泛型列表 我想做的与这个问题非常相似(但不相同): 不同的是,我希望列表中包含强类型对象,而不是数据行(另外,我这里还没有linq可用) 我关心表现。业务层方法将依次从表示层调用,结果将被迭代以显示给用户。在业务层添加一个额外的迭代似乎是非常浪费的,只是在演示文稿中立即再添加一次,所以我希望这是尽可能快的 这是一项常见的任务,因此我正在寻找一种可以反复重复的好模式。您是否提前知道数据表的结构和键
不同的是,我希望列表中包含强类型对象,而不是数据行(另外,我这里还没有linq可用) 我关心表现。业务层方法将依次从表示层调用,结果将被迭代以显示给用户。在业务层添加一个额外的迭代似乎是非常浪费的,只是在演示文稿中立即再添加一次,所以我希望这是尽可能快的
这是一项常见的任务,因此我正在寻找一种可以反复重复的好模式。您是否提前知道
数据表的结构和键入的对象?您可以使用委托来进行映射。如果您不这样做(即,您所知道的只是类型和属性),那么有一些方法可以加速动态成员访问(例如超描述符
)
两种方式,考虑迭代器块;这样,您就不必第二次缓冲整个对象;当然,如果你只处理少量的争吵,这不是问题
你能澄清其中任何一点吗?我可以添加更多的细节
最简单地说,这有什么问题:
DataTable table = new DataTable {
Columns = {
{"Foo", typeof(int)},
{"Bar", typeof(string)}
}
};
for (int i = 0; i < 5000; i++) {
table.Rows.Add(i, "Row " + i);
}
List<MyType> data = new List<MyType>(table.Rows.Count);
foreach (DataRow row in table.Rows) {
data.Add(new MyType((int)row[0], (string)row[1]));
}
DataTable=新的DataTable{
列={
{“Foo”,typeof(int)},
{“Bar”,typeof(string)}
}
};
对于(int i=0;i<5000;i++){
表.行.添加(i,“行”+i);
}
列表数据=新列表(table.Rows.Count);
foreach(table.Rows中的DataRow行){
添加(新的MyType((int)行[0],(string)行[1]);
}
(上面的问题可能会引导正确的方法…您将需要迭代数据行,并在某个时候将它们转换为您的对象,但是,您可以使用构造函数编写自定义集合,该构造函数接受数据行集合,并在请求时将每个项转换为对象类型,而不是一次将所有项都转换为对象类型
假设您定义了实现IList的自定义集合。然后,它可以有两个内部字段—一个对数据行集合的引用和一个列表。列表将被初始化为数据行集合的长度,但具有空值
现在在索引器中,您可以检查列表
是否在该索引处包含值,如果不包含值,您可以使用任何有用的方法创建对象,并在返回之前将其存储在那里
这将推迟对象的创建,直到它们被请求,并且您将只创建被请求的对象
您的对象可能需要一个接受数据行的构造函数,或者需要某种工厂来创建它们,但这是另一个主题 只是为了在一个简单的控制台应用程序中为Mark的答案提供更多的用户友好性:
class Program
{
static void Main(string[] args)
{
//define a DataTable obj
DataTable table = new DataTable
{
Columns = {
{"Foo", typeof(int)},
{"Bar", typeof(string)}
}
};
//populate it the DataTable
for (int i = 0; i < 3; i++)
{
table.Rows.Add(i, "Row " + i);
}
List<MyType> listWithTypedObjects= new List<MyType>(table.Rows.Count);
foreach (DataRow row in table.Rows)
{
listWithTypedObjects.Add(new MyType((int)row[0], (string)row[1]));
}
Console.WriteLine(" PRINTING THE POPULATED LIST ");
foreach (MyType objMyType in listWithTypedObjects)
{
Console.Write(" I have object of the type " + objMyType.ToString() + " => " );
Console.Write(" with Prop1OfTypeInt " + objMyType.Prop1OfTypeInt.ToString() + " , ");
Console.WriteLine(" with Prop1OfTypeInt " + objMyType.Prop2OfTypeString.ToString() + " ");
}
Console.WriteLine(" \n \n \n HIT A KEY TO EXIT THE PROGRAM ");
Console.ReadKey();
}
}
class MyType {
public int Prop1OfTypeInt { get; set; }
public string Prop2OfTypeString { get; set; }
/// <summary>
/// Note the order of the passed parameters is important !!!
/// </summary>
public MyType( int prop1OfTypeInt , string prop2OfTypeString)
{
this.Prop1OfTypeInt = prop1OfTypeInt;
this.Prop2OfTypeString = prop2OfTypeString;
}
}
类程序
{
静态void Main(字符串[]参数)
{
//定义数据表obj
DataTable=新的DataTable
{
列={
{“Foo”,typeof(int)},
{“Bar”,typeof(string)}
}
};
//将其填充到数据表中
对于(int i=0;i<3;i++)
{
表.行.添加(i,“行”+i);
}
List listWithTypedObjects=新列表(table.Rows.Count);
foreach(table.Rows中的DataRow行)
{
添加(新的MyType((int)行[0],(string)行[1]);
}
Console.WriteLine(“打印填充的列表”);
foreach(listWithTypedObjects中的MyType对象类型)
{
Write(“我有类型为“+objMyType.ToString()+”=>”)的对象;
Write(“with Prop1OfTypeInt”+objMyType.Prop1OfTypeInt.ToString()+”,”;
WriteLine(“with Prop1OfTypeInt”+objMyType.Prop2OfTypeString.ToString()+”);
}
Console.WriteLine(“\n\n\n按一个键退出程序”);
Console.ReadKey();
}
}
类MyType{
public int Prop1OfTypeInt{get;set;}
公共字符串Prop2OfTypeString{get;set;}
///
///请注意,传递参数的顺序很重要!!!
///
公共MyType(int-prop1OfTypeInt,string-prop2OfTypeString)
{
this.Prop1OfTypeInt=Prop1OfTypeInt;
this.Prop2OfTypeString=Prop2OfTypeString;
}
}
上述示例的问题是速度非常慢。我有一个数据表,大约有400行,这个转换需要5到6秒
这似乎是一项非常普通的任务,所以我很惊讶这里没有人有更高性能的解决方案
*更新*强>
为了好玩,我想我应该尝试使用LINQ进行转换,而不是迭代数据表并添加到列表中。以下是我所做的:
List<MyObject> returnList = new List<MyObject>();
MyDataTable dtMyData = new MyTableAdapter().GetMyData();
returnLists = (from l in dtMyData
select new MyObject
{
Active = l.IsActive,
Email = l.Email,
//...
//About 40 more properties
//...
ZipCode = l.Zipcode
}).ToList();
List returnList=newlist();
MyDataTable dtMyData=新建MyTableAdapter().GetMyData();
ReturnList=(从dtMyData中的l开始)
选择新的MyObject
{
活动=l.I活动,
电子邮件=l.电子邮件,
//...
//大约还有40多处房产
//...
ZipCode=l.ZipCode
}).ToList();
第一个方法(遍历每行)耗时5.3秒,使用LINQ的方法耗时1.8秒 public部分类发布接收\u manager文件\u bal
public partial class issuereceive_manageroffice_bal
{
public int issue_id{get;set;}
public string process{get;set;}
public DateTime issue_date{get;set;}
public TimeSpan issue_time{get;set;}
public string eg_no{get;set;}
public string lotno{get;set;}
public string clarity{get;set;}
public string sieves{get;set;}
public string shape{get;set;}
public double issue_carat{get;set;}
public int issue_pieces{get;set;}
public int receive_pieces{get;set;}
public double receive_carat{get;set;}
public int kp_pieces{get;set;}
public decimal kp_carat{get;set;}
public double loss{get;set;}
public string issue_manager{get;set;}
public string issue_by{get;set;}
public string receive_by{get;set;}
public int status{get;set;}
public DateTime receive_date{get;set;}
public string receive_time{get;set;}
public int factory_id{get;set;}
}
List<issuereceive_manageroffice_bal> issue_receive_list = new List<issuereceive_manageroffice_bal>();
issue_receive_list =
(from DataRow dr in DataTable.Rows
select new issuereceive_manageroffice_bal()
{
issue_id = 0,
issue_time = TimeSpan.Parse("0"),
receive_time = null,
shape = null,
process = dr["process"].ToString(),
issue_date = Convert.ToDateTime(dr["issue_date"]),
eg_no = dr["eg_no"].ToString(),
lotno = dr["lotno"].ToString(),
clarity = dr["clarity"].ToString(),
sieves = dr["sieves"].ToString(),
issue_carat = dr["issue_carat"].ToString() != "" ? double.Parse(dr["issue_carat"].ToString()) : 0,
issue_pieces = dr["issue_pieces"].ToString() != "" ? int.Parse(dr["issue_pieces"].ToString()) : 0,
receive_carat = dr["receive_carat"].ToString() != "" ? double.Parse(dr["receive_carat"].ToString()) : 0,
kp_pieces = dr["kp_pieces"].ToString() != "" ? int.Parse(dr["kp_pieces"].ToString()) : 0,
kp_carat = dr["kp_carat"].ToString() != "" ? decimal.Parse(dr["kp_carat"].ToString()) : 0,
loss = dr["loss"].ToString() != "" ? double.Parse(dr["loss"].ToString()) : 0,
issue_manager = dr["lotno"].ToString(),
issue_by = dr["issue_by"].ToString(),
receive_by = dr["receive_by"].ToString(),
status = dr["status"].ToString() != "" ? int.Parse(dr["status"].ToString()) : 0,
receive_date = Convert.ToDateTime(dr["receive_date"]),
factory_id = dr["factory_id"].ToString() != "" ? int.Parse(dr["factory_id"].ToString()) : 0,
}).ToList();
{
公共整数问题_id{get;set;}
公共字符串进程{get;set;}
公共日期时间问题\u日期{get;set;}
公共时间跨度发布时间{get;set;}
公共字符串如_no{get;set;}
公共字符串lotno{get;set;}
公共字符串清晰度{get;set;}
P
public List<dynamic> GetListFromDT(Type className, DataTable dataTable)
{
List<dynamic> list = new List<dynamic>();
foreach (DataRow row in dataTable.Rows)
{
object objClass = Activator.CreateInstance(className);
Type type = objClass.GetType();
foreach (DataColumn column in row.Table.Columns)
{
PropertyInfo prop = type.GetProperty(column.ColumnName);
prop.SetValue(objClass, row[column.ColumnName], null);
}
list.Add(objClass);
}
return list;
}
DataTable dtPersons; //populate this datatable
public class Persons{
public string Name {get; set;}
public int Age {get; set;}
}
List<dynamic> dynamicListReturned = GetListFromDT(typeof(Persons), dataTable);
List<Persons> listPersons = dynamicListReturned.Cast<Persons>().ToList();