LINQ嵌套连接

时间:2010-06-16 04:55:13

标签: linq join

我试图将SQL连接转换为LINQ。我需要一些帮助来使嵌套连接在LINQ中工作。

这是我的SQL查询,我只是简单地在SQL中显示嵌套连接:

select distinct 
 txtTaskStatus as TaskStatusDescription, 
    txtempfirstname+ ' ' + txtemplastname as RaisedByEmployeeName,
    txtTaskPriorityDescription as TaskPriorityDescription,
    dtmtaskcreated as itemDateTime, 
    dbo.tblTask.lngtaskid as TaskID, 
    dbo.tblTask.dtmtaskcreated as CreatedDateTime, 
    convert(varchar(512), dbo.tblTask.txttaskdescription) as ProblemStatement,
    dbo.tblTask.lngtaskmessageid, 
    dbo.tblMessage.lngmessageid as MessageID, 
    case when isnull(dbo.tblMessage.txtmessagesubject,'') <> '' then txtmessagesubject else left(txtmessagedescription,50) end as MessageSubject, 
    dbo.tblMessage.txtmessagedescription as MessageDescription, 
    case when dbo.tblMessage.dtmmessagecreated is not null then dbo.tblMessage.dtmmessagecreated else CAST(FLOOR(CAST(dtmtaskcreated AS DECIMAL(12, 5))) AS DATETIME) end as MessageCreatedDateTime

FROM 
 dbo.tblAction RIGHT OUTER JOIN dbo.tblTask ON dbo.tblAction.lngactiontaskid = dbo.tblTask.lngtaskid 
 LEFT OUTER JOIN dbo.tblMessage ON dbo.tblTask.lngtaskmessageid = dbo.tblMessage.lngmessageid 
 LEFT OUTER JOIN dbo.tblTaskCommentRecipient 
  RIGHT OUTER JOIN  dbo.tblTaskComment ON dbo.tblTaskCommentRecipient.lngTaskCommentID = dbo.tblTaskComment.lngTaskCommentID 
  ON dbo.tblTask.lngtaskid = dbo.tblTaskComment.lngTaskCommentTaskId

2 个答案:

答案 0 :(得分:6)

一位经验丰富的SQL程序员不会以这种方式加入。为了清晰起见,他们使用严格的左连接(因为有严格的左连接解决方​​案可用)。

我已经解开这些连接以产生层次结构:

Task
  Action
  Message
  TaskComment
    TaskCommentRecipient

在linq to sql designer中创建关联后,您可以达到层次结构的这些级别:

  //note: these aren't outer joins
from t in db.Tasks
let actions = t.Actions
let message = t.Messages
let comments = t.TaskComments
from c in comments
let recipients = c.TaskCommentRecipients
当集合为空时,

DefaultIfEmpty会生成一个默认元素。由于这些是数据库行,因此默认元素是空行。这就是左连接的行为。

query =
(
  from t in db.Tasks
  from a in t.Actions.DefaultIfEmpty()
  from m in t.Messages.DefaultIfEmpty()
  from c in t.Comments.DefaultIfEmpty()
  from r in c.Recipients.DefaultIfEmpty()
  select new Result()
  {
    TaskStatus = ???
    ...
  }
).Distinct();

除此之外:在一堆连接之后调用Distinct是一个拐杖。 #1看看你能否做到。 #2如果没有,请查看是否可以消除导致您必须调用它的任何错误数据。 #3如果没有,请在比整个查询更小的范围内调用Distinct。

希望这有帮助。

答案 1 :(得分:0)

SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[ShipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPostalCode], [t0].[ShipCountry]
FROM [Orders] AS [t0]
LEFT OUTER JOIN ([Order Details] AS [t1]
    INNER JOIN [Products] AS [t2] ON [t1].[ProductID] = [t2].[ProductID]) ON [t0].[OrderID] = [t1].[OrderID]

可写为

from o in Orders
join od in (
    from od in OrderDetails join p in Products on od.ProductID equals p.ProductID select od) 
    on o.OrderID equals od.OrderID into ood from od in ood.DefaultIfEmpty()
select o