具有多个表的左连接的Linq查询

时间:2012-03-26 16:23:42

标签: .net linq c#-4.0 entity-framework-4

这是我的linq查询

    from row in (
    from c in db.TabC
    from cpd in db.TabPD
    from slm in db.TabSLM
    where cpd.SLid == slm.SLid
    where c.Id == cpd.CID
    where c.O_Id == 1
    select new { c, cpd, slm })
group row in row.slm.SLType into g
select new
{
    SLType = g.Key,
    EStat = g.Count(r => r.c.EstatID != null),
    Training = g.Count(r => r.cpd.TrId != null),
    TrainingComplete =
        g.Count(r => r.cpd.TrStat == 44),
    AssessmentComplete =
        g.Count(r => r.cpd.CndAssess == 44)
};

我需要对表db.TabSLM进行左连接,并获得与该表中的记录一样多的记录。 TabC是主表,TabSLM也是如此。 TabPD具有引用TabC和TabSLM的详细记录。使用此查询,当TabP中没有TabC rowid或TabSLM rowid匹配时,我没有返回任何记录。我想要的是返回TabSLM中存在的记录数,如果没有匹配项。有关如何修改此查询的任何想法?

以下是列出最小字段的三个表中每个表的样本数据

TabC
ID  O_ID   Name
1       1     ABC
2       1     XYZ
3       1     RST

TabPD
RowID    CID    SLid 
1        2      1
2        1      1
3        3      2
4        ...

TabSLM
SLid   SLType
1      single level 
2      Multi level

通过上面的查询,我能够获得TabC.O_ID == 1的记录,但不能获取TabC.O_ID == 3的记录,因为TabC.O_ID没有ID == 3的任何记录。我仍然想要显示SLType,其他列显示为0

感谢您的时间......

2 个答案:

答案 0 :(得分:2)

您需要使用DefaultIfEmpty

var query =
    from row in (
      from c in db.TabC
      join cpd in db.TabPD on c.Id equals cpd.CID
      from slm in db.TabSLM.Where(x => cpd.SLid == x.SLid)
                           .DefaultIfEmpty()
      where c.O_Id == 1
      select new { c, cpd, slm })
group row by row.slm.SLType into g
select new
{
    SLType = g.Key,
    EStat = g.Count(r => r.c.EstatID != null),
    Training = g.Count(r => r.cpd.TrId != null),
    TrainingComplete =
        g.Count(r => r.cpd.TrStat == 44),
    AssessmentComplete =
        g.Count(r => r.cpd.CndAssess == 44)
};

答案 1 :(得分:0)

试试一次:

var query =
    from row in (
      from c in db.TabC
      join cpd in db.TabPD on c.Id equals cpd.CID into temp
                          from cpd in temp.DefaultIfEmpty()
      from slm in db.TabSLM.Where(x => cpd.SLid == x.SLid)
                           .DefaultIfEmpty()
      where c.O_Id == 1
      select new { c, cpd, slm })
group row by row.slm.SLType into g
select new
{
    SLType = g.Key,
    EStat = g.Count(r => r.c.EstatID != null),
    Training = g.Count(r => r.cpd.TrId != null),
    TrainingComplete =
        g.Count(r => r.cpd.TrStat == 44),
    AssessmentComplete =
        g.Count(r => r.cpd.CndAssess == 44)
};