2009-06-18 109 views
6

JOIN相当于我用下面的SQL查询工作:JOIN和LEFT在LINQ

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。我所有的表都有外键关系。

+1

您是否在使用Linq to SQL? – 2009-06-18 14:41:45

回答

5

你可能不得不稍微调整这一点,因为我正要离开袖口,但有一些重要的事情要记住。如果你的关系在你的dbml中正确设置,你应该能够隐式地进行内部连接,并且只需通过你的初始表访问数据。另外,LINQ中的左连接并不像我们希望的那样直截了当,你必须通过DefaultIfEmpty语法来实现它。我在这里创建了一个匿名类型,但您可能想要放入DTO类或其他类似的东西。我也不知道你想在空值的情况下做什么,但你可以使用?语法来定义一个值,如果该值为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); 
29
SELECT A.X, B.Y 
FROM A JOIN B ON A.X = B.Y 

这LINQ方法调用(加入)会产生上述的加入。

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方法调用(以群组加入,的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会生成与每个子记录匹配的父记录,如果没有其他匹配,则生成空子记录。为了从Linq的形状中获得Sql的形状,必须使用SelectMany解开子集记录集合,并使用DefaultIfEmpty处理空记录子集记录。

而且这里是我在linquifying的尝试,在这个问题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 } 
+0

你可以看看[这个问题](http://stackoverflow.com/q/12496809/442580)。 – capdragon 2012-09-19 19:27:03

1

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