我正在使用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?
编辑:请在下面查看我自己的答案。答案 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很棒!