LINQ中的JOIN和LEFT JOIN等价物

时间:2009-06-18 14:40:09

标签: sql linq join left-join

我正在使用以下SQL查询:

SELECT 
a.AppointmentId,
a.Status,
a.Type,
a.Title,
b.Days,
d.Description,
e.FormId
FROM Appointment a (nolock)
LEFT JOIN AppointmentFormula b (nolock)
ON a.AppointmentId = b.AppointmentId and b.RowStatus = 1
JOIN Type d (nolock)
ON a.Type = d.TypeId
LEFT JOIN AppointmentForm e (nolock)
ON e.AppointmentId = a.AppointmentId
WHERE a.RowStatus = 1
AND a.Type = 1
ORDER BY a.Type

我不确定如何在LINQ中实现JOIN。我的所有表都有外键关系。

3 个答案:

答案 0 :(得分:29)

SELECT A.X, B.Y
FROM A JOIN B ON A.X = B.Y

这个linq方法调用(加入)将生成上面的Join。

var query = A.Join
(
  B,
  a => a.x,
  b => b.y,
  (a, b) => new {a.x, b.y} //if you want more columns - add them here.
);

SELECT A.X, B.Y
FROM A LEFT JOIN B ON A.X = B.Y

这些linq方法调用(对GroupJoin,SelectMany,DefaultIfEmpty)将产生上面的Left Join

var query = A.GroupJoin
(
  B,
  a => a.x,
  b => b.y,
  (a, g) => new {a, g}
).SelectMany
(
  z => z.g.DefaultIfEmpty(),
  (z, b) =>
    new  { x = z.a.x, y = b.y } //if you want more columns - add them here.
);

这里的关键概念是Linq的方法产生分层形状的结果,而不是扁平的行列形状。

  • Linq的GroupBy生成的结果形式为层次结构,其分组键与集合元素(可能不为空)匹配。 SQL的GroupBy子句生成具有聚合值的分组键 - 没有可用的子集合。
  • 同样,Linq的GroupJoin生成一个分层形状 - 与父记录的集合匹配的父记录(可能为空)。 Sql的LEFT JOIN生成与每个子记录匹配的父记录,如果没有其他匹配则生成空子记录。要从Linq的形状获得Sql的形状,必须使用SelectMany解压缩子记录集合 - 并使用DefaultIfEmpty处理空的子记录集合。

这是我试图在问题中解释sql:

var query =
  from a in Appointment
  where a.RowStatus == 1
  where a.Type == 1
  from b in a.AppointmentFormula.Where(af => af.RowStatus == 1).DefaultIfEmpty()
  from d in a.TypeRecord //a has a type column and is related to a table named type, disambiguate the names
  from e in a.AppointmentForm.DefaultIfEmpty()
  order by a.Type
  select new { a.AppointmentId, a.Status, a.Type, a.Title, b.Days, d.Description, e.Form }

答案 1 :(得分:5)

当我离开袖口时,你可能需要略微调整一下,但有几个要记住的重要事项。如果在dbml中正确设置了关系,则应该可以隐式执行内部联接,只需通过初始表访问数据。此外,LINQ中的左连接并不像我们希望的那样直截了当,您必须通过DefaultIfEmpty语法才能实现它。我在这里创建了一个匿名类型,但您可能想要放入DTO类或其他类似的东西。在nulls的情况下我也不知道你想做什么,但你可以使用??语法定义一个值,如果值为null,则给出变量。如果您还有其他问题,请与我们联系......

var query = (from a in context.Appointment
join b in context.AppointmentFormula on a.AppointmentId equals b.AppointmentId into temp
from c in temp.DefaultIfEmpty()
join d in context.AppointmentForm on a.AppointmentID equals e.AppointmentID into temp2
from e in temp2.DefaultIfEmpty()
where a.RowStatus == 1 && c.RowStatus == 1 && a.Type == 1
select new {a.AppointmentId, a.Status, a.Type, a.Title, c.Days ?? 0, a.Type.Description, e.FormID ?? 0}).OrderBy(a.Type);

答案 2 :(得分:1)

如果你想保留(NOLOCK)提示,我在C#中使用扩展方法blogged a handy solution。请注意,这与向查询中的每个表添加nolock提示相同。