在LINQ中简单的左连接

时间:2011-02-02 14:18:22

标签: c# linq

我有一个私人消息表和一个用户表。

我在这里连接它们:

 var messageUsers = (from pm in dc.PrivateMessages
                                join user in dc.Users
                                on pm.SenderID equals user.UserID
                                where !pm.IsDeletedRecipient && pm.RecipientID == id
                                select new PMInbox
                                {
                                    SenderUsername = user.Username,
                                    PrivateMessageID = pm.PrivateMessageID,
                                    SenderID = pm.SenderID,
                                    Subject = pm.Subject,
                                    Text = pm.Text,
                                    SenderType = pm.SenderType,
                                    IsDeletedRecipient = pm.IsDeletedRecipient,
                                    IsDeletedSender = pm.IsDeletedSender,
                                    IsRead = pm.IsRead,
                                    Timestamp = pm.TimestampSend

                                }).ToList();

如何在左连接中进行此操作,因此如果userID不是SenderID(例如,已完全删除发件人),则用户名应为空?

2 个答案:

答案 0 :(得分:4)

var messageUsers = (
      from pm in dc.PrivateMessages
      where !pm.IsDeletedRecipient && pm.RecipientID == id
      select new PMInbox {
          SenderUsername = (
                from user in dc.Users
                where user.UserID == pm.SenderID
                select user.Username
              ).SingleOrDefault(),
          PrivateMessageID = pm.PrivateMessageID,
          //...
      }
    ).ToList();

通常,要在LINQ中实现Left外连接,当您希望包含连接的“table”的1或0行时,应该使用SingleOrDefaultFirstOrDefault,并{{ 1}}当你可能需要包含几个行时(根据我的经验,这是一个不太常见的场合)。在您的具体情况下,DefaultIfEmpty听起来像是UserID的唯一标识符 - 因此,我将您的左联接转换为Users来电,而不是SingleOrDefault来电。

与SQL不同,.NET无法解析空值的属性。因此,如果您执行DefaultIfEmptyuser.Username之类的操作为null,则会获得user。然后,您可以在每次访问NullReferenceException时检查空值,也可以在调用userselect之前投影(即SingleOrDefault 。毕竟,用户序列会选择用户名序列 - 在DefaultIfEmpty创建名称或SingleOrDefault之后,无需任何手册null - 检查。

答案 1 :(得分:1)

进行群组加入,然后通过查询来解压缩群组。当集合为空时,DefaultIfEmpty会生成一个null元素。

var messageUsers = (
  from pm in dc.PrivateMessages
  join u in dc.Users 
    on pm.SenderID equals u.UserID
    into users 
  from user in users.DefaultIfEmpty()
  where !pm.IsDeletedRecipient && pm.RecipientID == id 
...

此外,如果在dbml中的表之间设置了关联,则应该有一个从PrivateMessage到User的关系属性,可以用来更简单地表达查询。 (我将该属性命名为Senders,但它可能是自动命名为Users或Users1。您可以在dbml中重命名该属性。)

var messageUsers = (
   from pm in dc.PrivateMessages
   where !pm.IsDeletedRecipient && pm.RecipientID == id
   from user in pm.Senders.DefaultIfEmpty()
   ...