如何最小化linq查询并提高性能

时间:2013-10-25 12:49:49

标签: c#

var Table = new List();

var partlist = Table
    .AsEnumerable()
    .Where(row =>
    {
        if (!string.IsNullOrEmpty(row.Field<string>("Column1")) &&
            row.Field<string>("Column1").Equals(variableName1) &&
            !string.IsNullOrEmpty(row.Field<string>("Column2")) &&
            row.Field<string>("Column2").Equals(variableName2))
            return true;
        return false;
    })
    .Select(row =>
    {
        return new
        {
            PartNumber = row.Field<string>("HardwareType"),
            Number = row.Field<string>("HardwareSerialNo")
        };
    })
    .Distinct();

var distinctParts =
    partlist
        .Select(part => { return part.PartNumber; })
        .Distinct();

foreach (var distinctPart in distinctParts)
{
    var list = partlist.Where(part =>
    {
        if (part.PartNumber.Equals(distinctPart))
            return true;
        return false;
    })
    .Select(part => { return part.Number; })
    .Distinct();

    int quantity = list.Count();
    hwList[distinctPart] = quantity;
}

上面的代码运行正常,但执行时间很长。有没有办法最小化代码并提高性能。 请帮帮我

2 个答案:

答案 0 :(得分:4)

这里的问题是您没有使用正确的数据类型。对于distinctParts中的每个条目,都需要迭代partlist。这是一个很大的问题,因为partlist定义了查询而不是查询的结果。换句话说,对于foreach循环的每次迭代,执行partlist 查询,执行您为其定义的所有代码:

  1. 从行中提取数据
  2. 创建匿名类型的新实例
  3. 删除重复的条目。
  4. 这是由于LINQ查询的延迟性质。

    我会通过从partlist中提取直接包含您需要的数据的字典来解决此问题。这将只执行一次partlist查询:

    var parts = partlist.GroupBy(x => x.PartNumber)
                        .ToDictionary(x => x.Key,
                                      x => x.Select(y => y.Number)
                                            .Distinct().Count()));
    
    foreach (var kvp in parts)
        hwList[kvp.Key] = kvp.Value;
    

    请注意:我另外删除了对此distinctParts的需求 这应该快得多。

答案 1 :(得分:0)

你可以抽象出你的一些过滤但是我没有看到要加强的地方:

function bool IsMatch(row, column, match)
{
    var value = row.Field<string>(column);
    return !string.IsNullOrEmpty(value) && value.Equals(match);
}

只会让它更具可读性:

.Where(row => {
    return IsMatch(row, "Column1", variableName1) && 
           IsMatch(row, "Column2", variableName2);
 })

与你的匿名对象类似。如果你创建一个简单的小类,你可以将实现抽象到构造函数:

public class PartModel
{
    public PartModel(TableRow row)
    {
        PartNumber = row.Field<string>("HardwareType");
        Number = row.Field<string> ("HardwareSerialNo");
    }
    public string PartNumber { get; set; }
    public string Number { get; set; }
}

将其简化为:

.Select(row => { return new PartModel(row) }; })