以数据表转换为泛型列表的最快方法
-
22-07-2019 - |
题
我有,它返回一个数据表中的数据层选择方法。这是一个从业务层的方法则应该返回一个强类型的泛型列表,名为
我想要做的非常类似(但不一样)这样的问题:点击 怎样把一个DataTable变成泛型列表<? / A>
以往不同的是,我想在列表中包含强类型的对象,而不是数据行(也,我没有LINQ缴费这里还)。
我很担心性能。业务层的方法,将依次从表现层被调用,并且将结果迭代显示给用户。这似乎很浪费在业务层,只有再做一遍马上为演示文稿添加一个额外的迭代,所以我想这是尽可能快。
这是一个常见的任务,所以我真正需要的是可以重复一遍又一遍的良好格局。
解决方案
你知道DataTable
和提前的类型的对象的结构?你可以使用委托进行映射。如果不这样做(即,所有你知道是Type
和属性)有加速动态成员访问(如HyperDescriptor
)。
无论哪种方式,考虑迭代器块;这样你就不必缓冲对象的整个第二时间;当然,如果你只处理短小rowcounts这不是一个问题。
您可以澄清所有这些点的?我可以添加很多更详细...
目前最简单的,什么是错的:
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约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();
第一种方法(通过每个行迭代)代行5.3秒和使用LINQ方法把1.8秒!
您将需要通过数据行他们迭代,并转换成在某些时候你的对象,无论如何,但你可以写一个自定义集合与一个构造函数数据行的集合,当而是要求每个项目转换成你的对象类型各一次。
假设你定义自定义集合,实现IList<T>
。然后,它可以有两个内部字段 - 据行的集合和一个List<T>
参考。的List<T>
将被初始化为数据行的集合的长度,但具有空值。
现在的索引,你可以检查List<T>
包含索引处的值,如果没有,你可以创建一个使用任何手段将是有益的,并返回之前有它存储的对象。
这将推迟您的对象的创建,直到他们被要求与你只会创建被请求的对象。
您的对象可能会需要一个构造函数取一个DataRow或你需要某种形式的工厂来创建他们,但那是另一个话题。
只是提供一些更多的用户 - 在一个简单的控制台应用程序的友好马克的回答是:
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;
}
}
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();