Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.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
C# 在大型数据表中优化LINQ_C#_Performance_Linq_Datatable - Fatal编程技术网

C# 在大型数据表中优化LINQ

C# 在大型数据表中优化LINQ,c#,performance,linq,datatable,C#,Performance,Linq,Datatable,我有一个DataTable,它大约有800000行,由4列组成。起始位置、结束位置、距离和区域。我想做的是,对于特定区域中的每条记录,获取“相反”的记录,看看距离是否小于原始距离。此数据表中的每条记录都将有一条“相反”的记录 示例行及其“反面”如下所示: StartLoc | EndLoc | Distance | Zone 2, 1 4, 3 5 1 4, 3 2, 1 4 1 这里的问题是,当前的解决方案非常耗时

我有一个DataTable,它大约有800000行,由4列组成。起始位置、结束位置、距离和区域。我想做的是,对于特定区域中的每条记录,获取“相反”的记录,看看距离是否小于原始距离。此数据表中的每条记录都将有一条“相反”的记录

示例行及其“反面”如下所示:

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;
    }
public DataTable ProcessTable(DataTable\u tbl)
{
//将架构复制到新的datatable
DataTable ProcessedTable=_tbl.Clone();
foreach(数据行中的数据行)
{
var ReverseRow=来自数据行revRow in _tbl.Rows
其中revRow.Field(“EndLoc”)==row.Field(“EndLoc”)
其中revRow.Field(“EndLoc”)==row.Field(“EndLoc”)
其中revRow.Field(“区域”)==row.Field(“区域”)
选择revRow;
DataRow结果=ReverseRow.First();
int rowdance=行字段(“距离”);
int resultDistance=结果字段(“距离”);
如果(结果距离<行距离)
行[“距离”]=结果距离;
ProcessedTable.Rows.Add(row.ItemArray);
}
返回可处理;
}

我是LINQ noobie,所以这个问题有三个部分:

  • 有什么方法可以加快内部查询的速度吗
  • 我可以将foreach循环和查询合并到一个优雅的LINQ行中,并让它提高性能吗
  • 我是否完全错误地看待这一点,需要改变我的方法

  • 尝试加入。您正在克隆整个表,这可能是速度慢的原因

           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;
            }
    
    public DataTable ProcessTable(DataTable\u tbl)
    {
    //将架构复制到新的datatable
    var query=从r1开始,在_tbl.AsEnumerable()中
    从r2开始,可计算()
    式中(r1.字段(“终止点”)==r2.字段(“终止点”))
    &&(r1.字段(“EndLoc”)==r2.字段(“STARTOC”))
    &&(r1.字段(“区域”)==r2.字段(“区域”))
    选择新的{r1=r1,r2=r2};
    DataTable processedTable=query.Where(x=>x.r1.Field(“距离”)x.r1)
    .CopyToDataTable();
    返回可处理;
    }
    
    尝试加入。您正在克隆整个表,这可能是速度慢的原因

           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;
            }
    
    public DataTable ProcessTable(DataTable\u tbl)
    {
    //将架构复制到新的datatable
    var query=从r1开始,在_tbl.AsEnumerable()中
    从r2开始,可计算()
    式中(r1.字段(“终止点”)==r2.字段(“终止点”))
    &&(r1.字段(“EndLoc”)==r2.字段(“STARTOC”))
    &&(r1.字段(“区域”)==r2.字段(“区域”))
    选择新的{r1=r1,r2=r2};
    DataTable processedTable=query.Where(x=>x.r1.Field(“距离”)x.r1)
    .CopyToDataTable();
    返回可处理;
    }
    

    欢迎光临。这个问题在另一个Stack Exchange站点上可能会更好。也许是代码审查?任何人祝你好运你能考虑StasLoC/EndoLC/Stand独特的组合吗?您可以在它们上添加一个主键,并使用Find获得良好的性能。每对数据只需查询一次,无需解决数据一致性问题。如果从数据库获取DataTable,则应在数据库上执行查询,而不是获取整个表。欢迎使用。这个问题在另一个Stack Exchange站点上可能会更好。也许是代码审查?任何人祝你好运你能考虑StasLoC/EndoLC/Stand独特的组合吗?您可以在它们上添加一个主键,并使用Find获得良好的性能。每对数据只需一次,无需解决数据一致性问题。如果从数据库获取DataTable,则应在数据库上执行查询,而不是获取整个表。基本上就是这样。但是,为了使它更精确,您可以考虑从OP查询中添加其他条件到连接(也显示如何执行复合键连接)。谢谢您的快速响应,我现在得到内存不足的异常。有什么建议吗?你可以试着一次只得到一个区域。或者回到慢法。如果数据来自使用存储过程的SQL Server,则速度会更快。查询缺少基本条件,如果他以这种形式尝试,难怪它会返回废话,甚至崩溃。Ivan Stoev已经指出了这一点。OP在连接中有三个条件:
    a.startoc==b.EndLoc
    a.EndLoc==b.startoc
    a.Zone==b.Zone
    。你只有第一个。您并不是将每个记录与相反的记录进行比较,而是与更多的记录进行比较。而不是400000对,你可以很容易地像400000000对和最糟糕的,结果是不正确的。基本上就是这样。但是,为了使它更精确,您可以考虑从OP查询中添加其他条件到连接(也显示如何执行复合键连接)。谢谢您的快速响应,我现在得到内存不足的异常。有什么建议吗?你可以试着一次只得到一个区域。或者回到慢法。如果数据来自使用存储过程的SQL Server,则速度会更快。如果查询缺少基本条件,则