为了账号安全,请及时绑定邮箱和手机立即绑定

LINQ中的左外连接

LINQ中的左外连接

阿波罗的战车 2019-05-30 12:47:57
LINQ中的左外连接如何在C#LINQ对象中不使用join-on-equals-into条款?有没有办法where条款?正确的问题:因为内部连接很容易,我有这样的解决方案List<JoinPair> innerFinal = (from l in lefts from r in rights where l.Key == r.Key                              select new JoinPair { LeftId = l.Id, RightId = r.Id})但对于左外接,我需要一个解决方案。我的是这样的,但不起作用List< JoinPair> leftFinal = (from l in lefts from r in rights                             select new JoinPair {                                              LeftId = l.Id,                                              RightId = ((l.Key==r.Key) ? r.Id : 0                                         })JoinPair是一个类:public class JoinPair { long leftId; long rightId; }
查看完整描述

4 回答

?
MMTTMM

TA贡献1869条经验 获得超4个赞

如下文所述:

101 LINQ样本.左外连接

var q =
    from c in categories
    join p in products on c.Category equals p.Category into ps    from p in ps.DefaultIfEmpty()
    select new { Category = c, ProductName = p == null ? "(No products)" : p.ProductName };


查看完整回答
反对 回复 2019-05-30
?
神不在的星期二

TA贡献1963条经验 获得超6个赞

如果使用数据库驱动的LINQ提供程序,则可以这样编写更易读的左外部联接:

from maintable in Repo.T_Whatever 
from xxx in Repo.T_ANY_TABLE.Where(join condition).DefaultIfEmpty()

如果你忽略了DefaultIfEmpty()你会有一个内在的连接。

接受的答案:

  from c in categories
    join p in products on c equals p.Category into ps    from p in ps.DefaultIfEmpty()

这个语法非常混乱,当您想离开JOIN多个表时,不清楚它是如何工作的。


应该指出,from alias in Repo.whatever.Where(condition).DefaultIfEmpty()与外部应用/左连接横向相同,任何(体面的)数据库优化器都完全能够将其转换为左连接,只要您不引入一行值(也就是实际的外部应用)。不要在Linq-2对象中这样做(因为当您使用Linqto-Objects时没有DB优化器)。

详细实例

var query2 = (
    from users in Repo.T_User    from mappings in Repo.T_User_Group         .Where(mapping => mapping.USRGRP_USR == users.USR_ID)
         .DefaultIfEmpty() // <== makes join left join
    from groups in Repo.T_Group         .Where(gruppe => gruppe.GRP_ID == mappings.USRGRP_GRP)
         .DefaultIfEmpty() // <== makes join left join

    // where users.USR_Name.Contains(keyword)
    // || mappings.USRGRP_USR.Equals(666)  
    // || mappings.USRGRP_USR == 666 
    // || groups.Name.Contains(keyword)

    select new
    {
         UserId = users.USR_ID        ,UserName = users.USR_User        ,UserGroupId = groups.ID        ,GroupName = groups.Name
    });var xy = (query2).ToList();

当与LINQ 2 SQL一起使用时,它将很好地转换成以下非常清晰的SQL查询:

SELECT 
     users.USR_ID AS UserId 
    ,users.USR_User AS UserName 
    ,groups.ID AS UserGroupId 
    ,groups.Name AS GroupName FROM T_User AS users

LEFT JOIN T_User_Group AS mappings
   ON mappings.USRGRP_USR = users.USR_ID

LEFT JOIN T_Group AS groups
    ON groups.GRP_ID == mappings.USRGRP_GRP

编辑:

亦见“将SQLServer查询转换为Linq查询“一个更复杂的例子。

另外,如果您在Linq-2-对象(而不是Linq-2-SQL)中执行此操作,则应该采用老式的方法(因为LINQ to SQL可以正确地将其转换为联接操作,但是对于对象,此方法强制进行完全扫描,并且不利用索引搜索,为什么.):

    var query2 = (
    from users in Repo.T_Benutzer
    join mappings in Repo.T_Benutzer_Benutzergruppen on mappings.BEBG_BE equals users.BE_ID into tmpMapp
    join groups in Repo.T_Benutzergruppen on groups.ID equals mappings.BEBG_BG into tmpGroups    from mappings in tmpMapp.DefaultIfEmpty()
    from groups in tmpGroups.DefaultIfEmpty()
    select new
    {
         UserId = users.BE_ID        ,UserName = users.BE_User        ,UserGroupId = mappings.BEBG_BG        
         ,GroupName = groups.Name
    });


查看完整回答
反对 回复 2019-05-30
  • 4 回答
  • 0 关注
  • 999 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信