如何在具有多个表连接的linq中执行左连接

时间:2015-05-27 13:16:20

标签: c# sql-server linq entity-framework

我有以下LinQ查询:

List<string> emails = (from u in context.User
                            join h in context.Hero
                            on u.UserID equals h.UserID
                            join hc in context.HeroCategory
                            on h.HeroID equals hc.HeroID
                            where
                            (hc.QuestionCategoryID == 1
                            && h.IsHeroAdmin) || h.IsHeroSuperAdmin
                            select u.EmailAddress).ToList<string>();

如果英雄属于某个类别且他是管理员或英雄是超级管理员,我正在尝试获取电子邮件列表。

当我尝试使用左连接在sql中编写上述查询时,我得到了正确的结果:

SELECT 
    U.EmailAddress
FROM USERS U LEFT JOIN
    Heroes H ON (U.UserID=H.UserID) LEFT JOIN
    HeroCategory HC ON (H.HeroID=HC.HeroID)
WHERE (HC.QuestionCategoryID=1 AND H.IsHeroAdmin=1)
   OR H.IsHeroSuperAdmin=1

基本上我想知道在上面提到的linq查询中执行简单的左连接。

2 个答案:

答案 0 :(得分:1)

像这样的东西,但你应该在where子句中处理空值,因为如果你正在做left join那么为什么要过滤而不考虑空值?:

List<string> emails = (from u in context.User
                       join h in context.Hero on u.UserID equals h.UserID into hleft
                       from hl in hleft.DefaultIfEmpty()
                       join hc in context.HeroCategory on hl.HeroID equals hc.HeroID into hcleft
                       from hcl in hcleft.DefaultIfEmpty()
                       where
                       (hcl.QuestionCategoryID == 1
                       && hl.IsHeroAdmin) || hl.IsHeroSuperAdmin
                       select u.EmailAddress).ToList<string>();

答案 1 :(得分:0)

因为您在WHERE条款中测试了英雄的价值观,所以您已经有效地将英雄的LEFT JOIN变为INNER JOIN。唯一LEFT JOIN需要的是HeroCategory上的HeroCategory,然后只有当Hero不是超级拉丁时(再次,因为你测试QuestionCategoryId&#39; s {的价值{1}}如果他们不是SuperAdmin)。

你需要首先修复你的逻辑,但这里是等价的,假设Users to Heros是一对多的关系,HeroCategories是一对多:

var emails=context.Users
  .Where(u=>u.Heros.Any(h=>
      (h.IsHeroAdmin==1 && h.HeroCategories.Any(hc=>hc.QuestionCategoryID==1))
          || u.Heros.Any(h=>h.IsHeroSuperAdmin==1)))
  .Select(u=>u.EmailAddress)
  .ToList();

如果用户与Heros是1:1的关系,那么它将是这样的:

var emails=context.Users
  .Where(u=>(u.Heros.IsHeroAdmin==1 && h.Heros.HeroCategories.Any(hc=>hc.QuestionCategoryID==1)) || u.Heros.IsHeroSuperAdmin==1)
  .Select(u=>u.EmailAddress)
  .ToList();