实体框架+ Linq LEFT JOIN使用where子句?

时间:2014-02-16 00:30:46

标签: c# mysql linq entity-framework

我正在使用Linq和Entity Framework 5并使用查询语法(我想,请更正我的术语)。我有一个参与者表,并希望将他们的学习ID号与记录的SMS消息相关联,其中消息中的“to”或“from”号码与参与者的电话号码相匹配。此外,我希望从(或)未知号码发送的消息也显示在列表中,在这种情况下,研究ID号将为空。

这是LEFT JOIN的工作原始查询(如果重要的话,使用MySQL数据库):

SELECT
    messages._id, participants.study_id_number, messages.ts,
    messages.from_phone, messages.to_phone, messages.body
FROM messages LEFT JOIN
    participants ON (   (participants.phone_number = messages.to_phone)
                     || (participants.phone_number = messages.from_phone))
ORDER BY messages.ts DESC;

这是我到目前为止在Linq工作的内容,但它是一个内部联接:

var loggedMessages = from pp in theDb.participants
                     let phone = pp.phone_number
                     from mm in theDb.messages
                     let fromPhone = mm.from_phone
                     let toPhone = mm.to_phone
                     where ((phone == fromPhone) || (phone == toPhone))

                     orderby mm.ts descending
                     select new MessageLogEntry()
                     {
                         ParticipantId = pp.study_id_number,
                         TimeStamp = mm.ts,
                         FromPhone = fromPhone,
                         ToPhone = toPhone,
                         Body = mm.body
                     };

我是新手,所以我很高兴看到Linq查询教程的链接,但是我需要添加什么才能使它成为LEFT JOIN?

编辑:请在下面查看我自己的答案。

2 个答案:

答案 0 :(得分:4)

您需要添加 DefaultIfEmpty()以使其成为左连接。

检查一下:

var loggedMessages = from pp in theDb.participants
                     join mm in theDb.messages
                     on pp.phone_number equals mm.to_phone || 
                     pp.phone_number equals mm.from_phone
                     into joinedmm
                     from pm in joinedmm.DefaultIfEmpty()
                     orderby mm.ts descending
                     select new MessageLogEntry()
                     {
                         ParticipantId = pp.study_id_number,
                         TimeStamp = pm.ts,
                         FromPhone = fromPhone,
                         ToPhone = toPhone,
                         Body = pm.body
                     };

答案 1 :(得分:2)

经过一些快速而浅薄的研究,再加上一些SO链接,我得到了以下结果。评论非常受欢迎,我从这次练习中学到的最重要的事情就是我需要学习多少!

var loggedMessages = from mm in theDb.messages
                     from pp in theDb.participants
                     .Where(pp1 => ((mm.from_phone == pp1.phone_number) || (mm.to_phone == pp1.phone_number)))
                     .DefaultIfEmpty()
                     orderby mm.ts descending
                     select new MessageLogEntry()
                     {
                         ParticipantId = (int?)pp.study_id_number,
                         TimeStamp = mm.ts,
                         FromPhone = mm.from_phone,
                         ToPhone = mm.to_phone,
                         Body = mm.body
                     };

我对它从查询语法到方法语法再回来的方式感到有些惊骇,但是编译后,LinqPad喜欢它并显示正确的结果,并测试出来。我不知道它与性能如何相比是多么高效,这是未来的教训。

LinqPad很棒!