Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 将datatable转换为通用列表的最快方法_.net_.net 2.0_Datatable_N Tier Architecture - Fatal编程技术网

.net 将datatable转换为通用列表的最快方法

.net 将datatable转换为通用列表的最快方法,.net,.net-2.0,datatable,n-tier-architecture,.net,.net 2.0,Datatable,N Tier Architecture,我有一个返回datatable的数据层选择方法。它是从业务层方法调用的,然后该方法将返回一个强类型的泛型列表 我想做的与这个问题非常相似(但不相同): 不同的是,我希望列表中包含强类型对象,而不是数据行(另外,我这里还没有linq可用) 我关心表现。业务层方法将依次从表示层调用,结果将被迭代以显示给用户。在业务层添加一个额外的迭代似乎是非常浪费的,只是在演示文稿中立即再添加一次,所以我希望这是尽可能快的 这是一项常见的任务,因此我正在寻找一种可以反复重复的好模式。您是否提前知道数据表的结构和键

我有一个返回datatable的数据层选择方法。它是从业务层方法调用的,然后该方法将返回一个强类型的泛型列表

我想做的与这个问题非常相似(但不相同):

不同的是,我希望列表中包含强类型对象,而不是数据行(另外,我这里还没有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();