Linq to objects - 笨蛋?

Linq to objects - boondoggle?

我认为 LINQ to objects 是不同执行连接数据的好方法。实际上,它是一种糟糕的做事方式...

这是我们有的,在a,b,c,d中相应地有几、几百、3K和3.5K条记录

IEnumerable<MyModel> data =
    (from a in AList
     from b in BList.Where(r => r.AId == a.Id)
     from c in CList.Where(r => r.BId == b.Id)
     from d in DList.Where(r => r.SomeId == myId && r.Some2Id == c.Some2Id)
 //  . . . . . . 

LINQ 难道不应该很擅长做这件事吗? 实际上,跟随的速度要快得多,实际上快 60 倍

var dTemp = DList.Where(r => r.SomeId == myId).ToList();
var cTemp = CList.Where(c => dTemp.Any(d => d.Some2Id == c.Some2Id)).ToList();

IEnumerable<MyModel> data =
    (from a in AList
     from b in BList.Where(r => r.AId == a.Id)
     from c in cTemp.Where(r => r.BId == b.Id)
 //  . . . . . .

然后我遇到了this article

问:有没有办法在不放弃单个 LINQ 的情况下改进此查询?

或者这是否意味着如果性能受到威胁,需要避免使用 LINQ to objects in joins 并替换为一些顺序调用?

我们来分析一下差异。

第一个查询:您在 BList 上执行一个过滤器,在 CList 上执行一个过滤器,在 DList 上执行两个过滤器,全部在延迟执行的方式。然后您使用一种连接。
第二个查询:您在 DList 上执行静态过滤器并对其进行评估,在 CList 上基于 DList 执行另一个静态过滤器并对其进行评估,然后AListBList.

上的延迟执行过滤器

第二个查询更快,因为:

  • DList 未被视为无用值(由于之前的过滤器)
  • CList 由于之前的过滤器
  • 只包含有用的值

无论如何,这两个查询都是错误的。多个from基本上就是一个cross-joinas explained here。正如@Reddog 评论的那样,最好的方法是实际使用 Join:

var data = from a in AList
           join b in BList on a.Id equals b.AId
           join c in CList on b.Id equals c.BId
           join d in DList on c.Some2Id equals d.Some2Id
           where d.SomeId == someId;