Entity Framework Dołącz 3 tabele

140

Próbuję dołączyć do trzech stołów, ale nie rozumiem metody ...

Skończyłem dołączyć do 2 stołów

        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);

stoły

Chciałbym dołączyć tabelę tbl_Title z TID PK i uzyskać pole Tytuł .

Wielkie dzięki

Erçin Dedeoğlu
źródło
Przeczytaj ten powiązany artykuł. Nie używa notacji Method, ale powinieneś być w stanie zrozumieć sedno ... stackoverflow.com/questions/11204367/
xspydr
Pokaż zdjęcie z rozszerzonymi właściwościami nawigacji. Właściwości nawigacji to gotowe łączenia.
Gert Arnold,

Odpowiedzi:

84

Nie jest to testowane, ale uważam, że składnia powinna działać w przypadku zapytania lambda. Gdy łączysz więcej tabel za pomocą tej składni, musisz zagłębiać się w nowe obiekty, aby osiągnąć wartości, którymi chcesz manipulować.

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);
Pynt
źródło
18
To jest ohydne. Gdybym kiedykolwiek znalazł takie zapytanie w kodzie produkcyjnym, natychmiast je refaktoryzowałem. Jednak +1 za udzielenie odpowiedzi na zadane pytanie!
Dan Bechard
8
@Dan Z ciekawości, czy to po prostu nie przemyślane w ogóle konwencje nazewnictwa z c, cm i ccm, czy po prostu składnia wymagana do wykonywania złączeń za pomocą linq i lambda jest ohydna? Jeśli pierwszy, i chciałbyś edytować post, aby miał lepszy układ, z pewnością to masz. Wciąż jestem nowy w strukturze encji i nadal wykorzystuję najlepsze praktyki, więc jeśli masz sugestie, aby ta odpowiedź była bardziej wymowna dla przyszłych użytkowników, będę wdzięczny za pomoc.
Pynt
4
Nie zastanawiałem się zbytnio nad dokładnym powodem, kiedy komentowałem, ale z pewnością konwencje nazewnictwa szkodzą czytelności (odwzorowanie skopiowane z OP). Ponadto przecinki na początku linii bardzo szkodzą czytelności (dla mnie subiektywne), a spacje / wcięcia można by nieco poprawić. Przesłałem edycję z wszystkimi tymi ulepszeniami (IMHO), odkąd o to poprosiłeś.
Dan Bechard
2
Formatowanie kodu jest często stronnicze, ale są pewne ogólne rzeczy, które według większości ludzi wyglądają lepiej. Jeśli chodzi o konwencje nazewnictwa, zwykłem nazywać rzeczy naprawdę krótkimi nazwami, ale teraz mogę pisać wystarczająco szybko (nawet nie biorąc pod uwagę rzeczy takich jak Intellisense), że kilka zapisanych znaków nie jest wartych uszczerbku dla czytelności w porównaniu z nazywaniem rzeczy werbalnie, np. „EntryID” kontra „EID”, „wpis łączony” kontra „cm” itp. W końcu ktoś inny będzie czytać mój kod i wolałbym, aby nie narastał do mnie nienawiści jako funkcja liniowa liczby wierszy mojego kod, który musieli przeczytać / utrzymać.
Dan Bechard
7
Po prostu nie rozumiem argumentów przeciwko przecinkom w wierszach początkowych. Jestem głęboko przekonany, ponieważ sprawia, że ​​komentowanie poszczególnych klauzul / argumentów jest naprawdę łatwe. I wygląda ładniej :-)
Auspex
213

Myślę, że będzie łatwiej używając zapytania opartego na składni:

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);

I prawdopodobnie powinieneś dodać orderbyklauzulę, aby upewnić się, że Top(10)zwraca prawidłowe dziesięć pierwszych pozycji.

MarcinJuraszek
źródło
4
Bardzo dziękuję za metodę; działa jasno, ale chciałbym zobaczyć odpowiedź, o którą prosiłem, jeszcze raz wielkie dzięki.
Erçin Dedeoğlu,
@MarcinJuraszek: jeśli potrzebuję ViewModel do działania, czy muszę dołączyć do stolików?
Vini
To nie działa nawet bez synchronizacji. Mam dokładny scenariusz, ale kwerenda zgłasza wyjątek [the_list_of_all_return_variables] „nie można serializować. @marcinJuraszek - Czy mógłbyś rzucić okiem na stackoverflow.com/questions/42453123/…
sandiejat
2
IDEALNY! zaoszczędziłeś mi tyle czasu :)
MohammadHossein R