LINQ中的JOIN和LEFT JOIN等价物

6

我正在处理以下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个回答

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

这个 Linq 方法调用(Join)将生成上述的 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)将产生上述左连接

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将一个父记录与每个子记录匹配,如果没有其他匹配,则将其设为null的子记录。要从Linq的形状转换到Sql的形状,必须使用SelectMany拆开子记录的集合,并使用DefaultIfEmpty处理空的子记录集合。

以下是将sql语句转换为Linq的尝试:

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 }

5

您可能需要稍微调整一下,因为我是根据经验来说的,但有几个重要的事情需要记住。如果您在dbml中正确设置了关系,您应该能够隐式地进行内部连接,并通过初始表访问数据。此外,在LINQ中进行左连接并不像我们希望的那样直接,您必须通过DefaultIfEmpty语法才能实现它。我在这里创建了一个匿名类型,但您可能想将其放入DTO类或类似的东西中。我也不知道在空值情况下您想要做什么,但您可以使用??语法来定义一个值,以便在值为空时给变量赋值。如果您有其他问题,请告诉我...

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);

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接