【问题标题】:Linq 'into' keyword confusionLinq 'into' 关键字混淆
【发布时间】:2020-12-19 07:02:19
【问题描述】:

我正在查看一个同事的 Linq 查询,如下所示(查询正确执行):

from ea in EquipmentApplication
join erl in EquipmentRoutingLocation on ea.EquipmentID equals erl.EquipmentID into erlWithNulls

from erlAll in erlWithNulls.DefaultIfEmpty()
join rl in RoutingLocation on erlAll.RoutingLocationID equals rl.RoutingLocationID into rlWithNulls

from rlAll in rlWithNulls.DefaultIfEmpty()
where ea.Equipment.Master_Cell.Area.Unit.UnitID == 1160
select new { ea.Equipment, ea.ApplicationFriendlyName, rlAll }

我很困惑为什么会这样。我的理解(可能是错误的)是“into”关键字结束了当前的范围/上下文(并且创建的任何变量现在都超出了范围)并创建了一个新的。如果这是真的,为什么 'ea' 变量仍在查询的最后一部分的范围内?

【问题讨论】:

    标签: linq


    【解决方案1】:

    当与 select 关键字一起使用时,into 将结束作用域。
    当与join 关键字一起使用时,into 将添加一个变量,其中包含来自连接的所有匹配项。 (这称为Group Join

    【讨论】:

    • 因此,当您使用多个连接时,您是否使用“into”子句并将下一个查询与您刚刚添加的“变量”连接起来?
    【解决方案2】:

    “进入”有两种不同的含义:

    • join 子句中,它将翻译从使用Join 更改为GroupJoin。这意味着不是每个匹配对获得一个结果,而是为原始序列的每个元素获得一个结果,并且该结果包含键和来自另一个序列的所有结果,作为一个组。详情请见Enumerable.GroupJoin
    • selectgroup...by 中,它变为query continuation,有效地使用新范围变量中旧查询的结果启动新查询。

    【讨论】:

    • 链接Query continuation不再有效!
    【解决方案3】:

    为了补充已经说过的内容,我想展示 into 与 without 产生的对象结构的区别:

    var q = 
        from c in categories 
        join p in products on c equals p.Category into ps 
        select new { Category = c, Products = ps }; 
    

    创建一个对象图:

    Category 1, Products:
      Product 1
      Product 2
    Category 2, Products:
      Product 3
      Product 4
    

    在这种情况下,q 只包含 2 个项目,两个类别。

    没有 into,您将获得更传统的连接,通过创建所有可能的组合来扁平化关系:

    var q = 
        from c in categories 
        join p in products on c equals p.Category 
        select new { Category = c, Product = p }; 
    
    Category 1, Product 1
    Category 1, Product 2
    Category 2, Product 3
    Category 2, Product 4
    

    请注意,现在 q 包含 4 个项目。

    回应评论:

    var q = 
        from c in categories 
        join p in products on c equals p.Category into ps 
        select new { Category = c, Products = ps.Select(x=> x.Id) }; 
    

    【讨论】:

    • 在您的第一个示例中,不是选择整个产品 1、2 和 3、4。您如何只选择 ID 或产品 1、2 和 3、4?
    • @RayCheng 我这里没有要测试的设置,但我发布了另一个可能有效的代码 sn-p,您可能需要添加 ToList ps.Select( --- ).ToList()
    猜你喜欢
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    • 2023-04-01
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多