在大型数据表中优化LINQ

时间:2017-05-27 12:23:20

标签: c# performance linq datatable

我的DataTable有大约800,000行,由4列组成。 StartLocation,EndLocation,Distance和Zone。我想要做的是,对于该特定区域中的每个记录,获取“相反”记录并查看距离是否小于原始记录。此DataTable中的每条记录都有一个“相反”记录。

一个示例行,它的“对面”如下所示:

StartLoc | EndLoc | Distance | Zone
 2, 1       4, 3     5         1
 4, 3       2, 1     4         1

这里的问题是当前的解决方案非常耗时且简单。下面的代码是现在采用的策略。

public DataTable ProcessTable(DataTable _tbl)
    {
        //copy the schema to new datatable
        DataTable ProcessedTable = _tbl.Clone();

        foreach (DataRow row in _tbl.Rows)
        {
            var ReverseRow = from DataRow revRow in _tbl.Rows
                             where revRow.Field<string>("StartLoc") == row.Field<string>("EndLoc")
                             where revRow.Field<string>("EndLoc") == row.Field<string>("StartLoc")
                             where revRow.Field<string>("Zone") == row.Field<string>("Zone")
                             select revRow;

            DataRow result = ReverseRow.First<DataRow>();

            int rowDistance = row.Field<int>("Distance");
            int resultDistance = result.Field<int>("Distance");

            if (resultDistance < rowDistance)
                row["Distance"] = resultDistance;

            ProcessedTable.Rows.Add(row.ItemArray);
        }

        return ProcessedTable;
    }

我是LINQ noobie,所以这个问题将包含3个部分:

  1. 有什么方法可以加快内部查询的速度吗?
  2. 我可以将foreach循环和查询合并到一个优雅的LINQ行,还能提高性能吗?
  3. 我认为这完全错了,需要改变我的方法吗?

1 个答案:

答案 0 :(得分:2)

尝试加入。您正在克隆可能导致速度慢的整个表格

       public DataTable ProcessTable(DataTable _tbl)
        {
            //copy the schema to new datatable

            var query = from r1 in _tbl.AsEnumerable()
                        from r2 in _tbl.AsEnumerable() 
                        where (r1.Field<string>("StartLoc") == r2.Field<string>("EndLoc"))
                           && (r1.Field<string>("EndLoc") == r2.Field<string>("StartLoc"))
                           && (r1.Field<string>("Zone") == r2.Field<string>("Zone")) 
                        select new { r1 = r1, r2 = r2 };

            DataTable processedTable = query.Where(x => x.r1.Field<int>("Distance") < x.r2.Field<int>("Distance"))
                                             .Select(x => x.r1)
                                             .CopyToDataTable();

            return processedTable;
        }