实体框架联接3个表


133

我正在尝试加入三个表,但我不明白该方法...

我完成了加入2张桌子

        var entryPoint = dbContext.tbl_EntryPoint
            .Join(dbContext.tbl_Entry,
                c => c.EID,
                cm => cm.EID,
                (c, cm) => new
                {
                    UID = cm.OwnerUID,
                    TID = cm.TID,
                    EID = c.EID,
                }).
            Where(a => a.UID == user.UID).Take(10);

桌子

我想在TID PK中包含tbl_Title表,并获取Title字段。

非常感谢


查看此相关文章。它不使用方法的符号,但是,你应该能够得到的要点... stackoverflow.com/questions/11204367/...
xspydr

请显示带有扩展导航属性的图片。导航属性是现成的联接。
Gert Arnold

Answers:


202

我认为使用基于语法的查询会更容易:

var entryPoint = (from ep in dbContext.tbl_EntryPoint
                 join e in dbContext.tbl_Entry on ep.EID equals e.EID
                 join t in dbContext.tbl_Title on e.TID equals t.TID
                 where e.OwnerID == user.UID
                 select new {
                     UID = e.OwnerID,
                     TID = e.TID,
                     Title = t.Title,
                     EID = e.EID
                 }).Take(10);

您可能应该添加orderby子句,以确保Top(10)返回正确的前十项。


3
非常感谢您的方法;工作清晰,但我想按我的要求查看答案,再次感谢。
ErçinDedeoğlu

@MarcinJuraszek:如果我需要一个ViewModel来工作,是否有必要我加入表格?
维尼

即使没有异步,这也不起作用。我有确切的情况,但是查询抛出异常[the_list_of_all_return_variables]'无法序列化。@marcinJuraszek-您能看看stackoverflow.com/questions/42453123/…–
sandiejat

1
完善!您为我节省了很多时间:)
MohammadHossein R

81

这未经测试,但我认为该语法应适用于lambda查询。当您使用此语法连接更多表时,必须进一步深入到新对象中,以达到要操作的值。

var fullEntries = dbContext.tbl_EntryPoint
    .Join(
        dbContext.tbl_Entry,
        entryPoint => entryPoint.EID,
        entry => entry.EID,
        (entryPoint, entry) => new { entryPoint, entry }
    )
    .Join(
        dbContext.tbl_Title,
        combinedEntry => combinedEntry.entry.TID,
        title => title.TID,
        (combinedEntry, title) => new 
        {
            UID = combinedEntry.entry.OwnerUID,
            TID = combinedEntry.entry.TID,
            EID = combinedEntry.entryPoint.EID,
            Title = title.Title
        }
    )
    .Where(fullEntry => fullEntry.UID == user.UID)
    .Take(10);

17
太可怕了 如果我在生产代码中发现了这样的查询,我会立即对其进行重构。+1可以回答问题,不过!
Dan Bechard

8
@Dan出于好奇,是不是在所有使用c,cm和ccm的命名约定中都没有想到过,还是仅仅是使用linq和lambda执行联接所需要的语法是可怕的?如果是前者,而您想编辑帖子以使其具有更好的布局,则一定要这样做。我对实体框架还是陌生的,并且仍然沉浸在最佳实践中,因此,如果您有建议让此答案对将来的用户更加有说服力,我将非常感谢您的帮助。
Pynt

4
当我发表评论时,我并没有给出确切的原因,但可以肯定的是,命名约定会损害可读性(从OP复制而来)。此外,逗号作为行的开头会严重损害可读性(对我来说是主观的),并且空格/缩进可以略微改善。自您提出要求以来,我已经提交了所有这些(IMHO)改进内容的编辑。
丹·贝查德

2
代码格式通常有偏差,但是有些大多数人都认为看起来更好的一般事物。至于命名约定,我曾经称其为真正的短名称,但是现在我可以足够快地键入内容(甚至不考虑Intellisense之类的东西),相对于冗长地命名(例如“ EntryID”)而言,保存的几个字符在可读性方面不值得相对于“ EID”,“ combinedEntry”与“ cm”等。最终,其他人将要阅读我的代码,我希望他们不要因为我的行数成线性函数而对我产生仇恨他们必须阅读/维护的代码。
丹·贝查德

5
我只是没有反对逗号开头的论点。我是坚定的信徒,因为它使注释单个子句/自变量变得非常容易。它看起来更漂亮:-)
Auspex
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.