【问题标题】:What is the fastest way to fill a simple object from a DataTable?从 DataTable 填充简单对象的最快方法是什么?
【发布时间】:2015-02-05 17:56:37
【问题描述】:

我只是想知道是否有更快或更有效的方法将 DataTable 转换为对象?

我目前使用的方法是这样的:

public class Job {
    int JobID { get; set; }
    decimal JobCost { get; set; }

    Job(DataRow dr)
    {
        ID = Convert.ToInt32(dr["ID"]);
        if(dr["JobCost "] != DBNull.Value)
            JobCost = Convert.ToDecimal(dr["DelAmt"]);
    }
}

public static List<Job> FillObjects()
{
    DataTable dtJobs = JobController.GetJobTable();

    foreach (DataRow dr in dtJobs.Rows)
    {
        jobs.Add(new Job(dr));          
    }

    return jobs
}

这是一个明显简化的示例,但是由于数据表中有很多行并且对象中有很多属性,这会变得相当慢。有没有更快或更有效的方法来做这样的事情?

提前感谢您的任何回复!

【问题讨论】:

  • 想必数据表中的项目实际上是整数和小数。你应该铸造他们,而不是打电话给Convert。强制转换比操作更简单。除此之外,除了遍历每一行,提取每一个值,并将其分配给对象的字段之外,真的别无选择。
  • 这些项目主要是整数和小数,但数据库类型和代码中的变量类型之间并不总是有确切的关系。 (免责声明:这不是我的代码,我继承了系统)。有些数据库字段是字符串,需要转换成整数或日期时间等。
  • 那你真的应该解决这个问题了;将数字作为字符串存储在数据库中会导致许多不同类型的问题,其中之一当然是您的所有数据库查询都需要花费时间来解析所有查询结果。
  • 我同意。不幸的是,那些对管理层来说很难卖。他们非常有“如果它没有坏掉”的心态。再次感谢。

标签: c# asp.net system.data


【解决方案1】:

在不使用实体框架的情况下,您的选择仅限于您已经开发或使用 Linq 将它们放入对象中,例如:

dtJobs.AsEnumerable().Select(x=> new Job{
                                   ID = x.Field<int>("ID"),
                                   JobCost = x.Field<Decimal>("DelAmt")
});

这将返回一个可枚举的 Job 对象,然后你可以用它来做任何事情。您当前设置的一个警告是,这将不允许返回空值。如果您想这样做,请使用可为空的十进制字段并在 else where 处处理 null。

【讨论】:

  • 这种类型的操作使用 LINQ 会不会更慢?我知道可空类型,但这是在一个已经存在的系统中。可空类型与许多现有函数调用不兼容,因为您不能传递 int?作为一个整数。要完成这项工作,需要进行大量重写。
  • @user3241130 无论哪种方式都不会产生重大影响。
  • 很公平。谢谢你的回答。
【解决方案2】:

如果顺序不重要 - 您可以对数据行上的每个循环使用并行执行此操作。这将更快地处理。但是,在服务器应用程序上执行此操作必须小心。

注意:我更新为在添加列表时锁定列表。您还可以使用来自并发集合的集合,而不是使用锁。

  class Program
{
    static void Main(string[] args)
    {
        var sync = new Object();
        var dt = new DataTable();  // fill data
        var jobs = new List<Job>();
        Parallel.ForEach(dt.AsEnumerable(), row =>
        {
            var job = JobFactory.GetJob(row);
            lock (sync)
            {
                jobs.Add(job);
            }
        });
    }
}

public class JobFactory
{
    public static Job GetJob(DataRow d)
    {
        var j = new Job();

        // do processing here from data row to fill job object
        return j;
    }
}

public class Job
{

}

【讨论】:

  • List 不是为同时从多个线程访问而设计的。
  • 如果您只是要同步大部分工作,那么并行化它是没有意义的。最终结果几乎肯定会比序列化解决方案
  • 这实际上取决于从数据行加载每个对象需要多长时间,以及线程必须等待多长时间才能将结果转储到树中。证明任一理论的唯一方法是针对您要解决的问题进行测试。我发现在某些情况下速度较慢,但​​在其他情况下速度更快。 YMMV!!!!
猜你喜欢
  • 2015-05-28
  • 1970-01-01
  • 2019-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-31
  • 2023-04-06
相关资源
最近更新 更多