LINQ:左连接和右连接具有双重选择

时间:2019-02-20 14:48:56

标签: c# .net sql-server linq

我正在寻找一种在以下LINQ查询中具有表PART的所有内容的解决方案(我想通过添加一个右/左联接):

var query = (from p in db.PARTS
             join oc in db.OUTPUT_CONTROLS on p.id equals oc.partid
             join f in db.FCT on p.fct equals f.id
             select new
             { p.id, p.plant, p.unit, p.type, p.num, f.name, oc.datetime, oc.ncr } 
             into x
             group x by new 
             { x.id, x.plant, x.unit, x.type, x.num, x.name } 
             into g
             select new 
             { g.Key.id, g.Key.plant, g.Key.unit, g.Key.type, g.Key.num, g.Key.name, startdate = g.Min(oc => oc.datetime), endate = g.Max(oc => oc.datetime), sumncr = g.Sum(oc => oc.ncr) })
             .OrderByDescending(oc => oc.startdate);

谢谢

2 个答案:

答案 0 :(得分:1)

由于这篇文章,我自己找到了解决方法:LINQ Left Join And Right Join

解决方案:

var query = (from p in db.PARTS
                             join oc in db.OUTPUT_CONTROLS on p.id equals oc.partid into joined
                             join f in db.FCT on p.fct equals f.id
                             from j in joined.DefaultIfEmpty()
                             select new
                             { p.id, p.plant, p.unit, p.type, p.num, f.name, j.datetime, j.ncr } into x
                             group x by new { x.id, x.plant, x.unit, x.type, x.num, x.name } into g
                             select new { g.Key.id, g.Key.plant, g.Key.unit, g.Key.type, g.Key.num, g.Key.name, startdate = g.Min(oc => oc.datetime), endate = g.Max(oc => oc.datetime), sumncr = g.Sum(oc => oc.ncr) })
                             .OrderByDescending(oc => oc.startdate);

答案 1 :(得分:0)

如果您有一个SQL,在其中看到一个联接,然后是一个GroupJoin,请考虑使用LINQ GroupJoin。

在需要“学校与学生”,“客户与他们的订单”,“动物园与他们的动物”的情况下,您经常会看到这种情况。

似乎您有3个表:Parts,OutputControls和Fcts。

每个零件都有零个或多个OutputControl,每个OutputControl都使用外键PartId完全属于一个零件:直接的一对多关系

零件具有外键FctId,它指向零件的Fct。

您需要零件(的某些属性)及其输出控件及其Fct

var result = parts.GroupJoin(outputControls,   // GroupJoin Parts and OutputControls
    part => part.Id,                           // from every part take the Id
    outputControl => outputControl.PartId,     // from every outputControl take the PartId

    // result selector: when these Ids match,
    // use the part and all its matching outputControls to make one new object:
    (part, outputControlsOfThisPart) => new
    {
        // select the part properties you plan to use:
        Id = part.id,
        Plant = part.plant,
        Unit = part.unit

        // the output controls of this part:
        OutputControls = outputControlsOfThisPart.Select(outputControl => new
        {
             // again, select only the output control properties you plan to use
             Id = outputControl.Id,
             Name = outputControl.Name,
             ...
        })
        .ToList(),

        // For the Fct, take the Fct with Id equal to Part.FctId
        Fct = Fcts.Where(fct => fct.Id == part.Fct)
                  .Select(fct => new
                  {
                      // select only the Fct properties you plan to use
                      Id = fct.Id,
                      Name = fct.Name,
                      ...
                  })
                  // expect only one such Fct
                  .FirstOrDefault(),
    });