EF LINQ mencakup banyak entitas dan bersarang

155

Ok, saya memiliki entitas bertingkat tiga dengan hierarki berikut: Kursus -> Modul -> Bab

Inilah pernyataan EF LINQ asli:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters))
                .Single(x => x.Id == id); 

Sekarang, saya ingin memasukkan entitas lain bernama Lab yang dikaitkan dengan kursus.

Bagaimana cara saya memasukkan entitas Lab?

Saya mencoba yang berikut tetapi tidak berhasil:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters) && i.Lab)
                .Single(x => x.Id == id); 

Adakah ide untuk memasukkan Entitas Kedua?

Setiap saran atau informasi akan sangat dihargai. Terima kasih!

AnimaSola
sumber
1
Menambahkan yang lain .Includeharus berfungsi kecuali jika Anda bermaksud bahwa penambahan tambahan adalah cucu Kursus. Lihat ini atau opsi yang lebih baik adalah ini
von v.
Terkait / kemungkinan duplikat stackoverflow.com/q/3356541
StuartLC

Jawaban:

234

Sudahkah Anda mencoba menambahkan yang lain Include:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters))
                .Include(i => i.Lab)
                .Single(x => x.Id == id);

Solusi Anda gagal karena Includetidak menggunakan operator boolean

Include(i => i.Modules.Select(s => s.Chapters) &&          i.Lab)
                           ^^^                  ^             ^ 
                          list           bool operator    other list

Perbarui Untuk mempelajari lebih lanjut, unduh LinqPad dan lihat sampel. Saya pikir ini adalah cara tercepat untuk mengenal Linq dan Lambda.

Sebagai permulaan - perbedaan antara Selectdan Includeadalah bahwa dengan Pilih Anda memutuskan apa yang ingin Anda kembalikan (alias proyeksi). Sertakan adalah fungsi Eager Loading , yang memberi tahu Kerangka Entity bahwa Anda ingin menyertakan data dari tabel lain.

Sintaks Sertakan juga bisa dalam string. Seperti ini:

           db.Courses
            .Include("Module.Chapter")
            .Include("Lab")
            .Single(x => x.Id == id);

Tetapi sampel di LinqPad menjelaskan ini dengan lebih baik.

Jens Kloster
sumber
Menghargai itu! Di mana saya bisa belajar lebih banyak tentang ini? Saya terutama tertarik pada perbedaan antara Sertakan dan Pilih
AnimaSola
3
Hanya satu ini bekerja untuk saya: .Include("Module.Chapter"). Adakah yang tahu mengapa hal itu terjadi?
Jo Smo
5
@ JoSmo Anda perlu mengimpor namespace System.Data.Enityuntuk mengakses metode ekstensi. info lebih lanjut di sini
Jens Kloster
using System.Data.Entity;melakukannya. Terima kasih!
Jo Smo
1
dipilih untuk menyebutkan linqpad yang brilian, dan tip untuk menggunakan System.Data.Entity, thx Jens
Mike
38

Di Entity Framework Core ( EF.core) Anda bisa menggunakan .ThenIncludeuntuk memasukkan level selanjutnya.

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
    .ToList();

Informasi lebih lanjut: https://docs.microsoft.com/en-us/ef/core/querying/related-data

Catatan: Katakanlah Anda perlu beberapa ThenInclude()di blog.Posts, hanya mengulang Include(blog => blog.Posts)dan melakukan yang lain ThenInclude(post => post.Other).

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Other)
 .ToList();
Nick N.
sumber
Di EF.core saya sepertinya tidak bisa melakukan. Sertakan (i => i.Modules.Select (s => s.Chapters)), khususnya. Pilih di dalam. Sertakan. Adakah yang bisa mengkonfirmasi atau berbicara dengan?
ttugates
@ttugates Apa yang ingin Anda lakukan dengan pilih ini? Saya pikir apa yang ingin Anda lakukan adalah persis apa yang Anda lakukan dengan ThenIncludeinti EF. Mungkin membuat pertanyaan dengan contoh yang baik, sehingga kita bisa menjawabnya.
Nick N.
@Nick N - Kerangka kerja Entitas Linq Query: Cara ke Mana pada Multiple Nav Properties dan Pilih dari 3rd Nav Property . Karena apa yang saya Pilih bukan yang saya cocokkan, Termasuk tidak diperlukan sehingga pertanyaannya adalah tangensial. Pertanyaan saya mungkin terlalu "sempit" tetapi menghargai bantuan apa pun.
ttugate
1
Ah. Sebenarnya, .ThenInclude () berfungsi. Hanya butuh selamanya untuk intellisense untuk menampilkan tabel terkait.
Chris J
23

Includeadalah bagian dari antarmuka yang lancar, sehingga Anda dapat menulis beberapa Includepernyataan satu sama lain berikut

 db.Courses.Include(i => i.Modules.Select(s => s.Chapters))
           .Include(i => i.Lab)
           .Single(x => x.Id == id); 
Ilya Ivanov
sumber
menghargai itu! dapatkah Anda mengarahkan saya ke tempat saya dapat mempelajari lebih lanjut tentang ini? Terima kasih!
AnimaSola
1
Apakah Anda tahu apa itu sintaks jika Modul memiliki banyak tabel yang ingin Anda gabungkan? Katakan itu tautan ke Bab dan sesuatu yang lain?
David Spence
Apakah fasih bagian dari .Net atau apakah ini perpustakaan yang perlu diinstal?
codea
19

Anda juga bisa mencoba

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);
Martin Larsson
sumber
4
Terima kasih - notasi titik dalam string sangat berguna
Evert
1
Ini bisa bermanfaat, tetapi, satu alasan untuk tidak menggunakan ini adalah kemudahan refactoring nanti: jika Anda mengganti nama entitas "Bab" di beberapa titik, contoh lain akan secara otomatis diganti namanya. Lain adalah bahwa kesalahan akan ditemukan lebih cepat: pada waktu kompilasi, bukan waktu berjalan.
MGOwen
2

Seseorang dapat menulis metode ekstensi seperti ini:

    /// <summary>
    /// Includes an array of navigation properties for the specified query 
    /// </summary>
    /// <typeparam name="T">The type of the entity</typeparam>
    /// <param name="query">The query to include navigation properties for that</param>
    /// <param name="navProperties">The array of navigation properties to include</param>
    /// <returns></returns>
    public static IQueryable<T> Include<T>(this IQueryable<T> query, params string[] navProperties)
        where T : class
    {
        foreach (var navProperty in navProperties)
            query = query.Include(navProperty);

        return query;
    }

Dan gunakan seperti ini bahkan dalam implementasi generik:

string[] includedNavigationProperties = new string[] { "NavProp1.SubNavProp", "NavProp2" };

var query = context.Set<T>()
.Include(includedNavigationProperties);
Mohsen Afshin
sumber
Saya sudah mencoba jawaban Anda, tetapi itu melempar stackoverflowexceptions karena loop tak terbatas dengan dirinya sendiri.
Victoria S.
1
@VictoriaS., Anda dapat mengganti nama metode ekstensi agar tidak mengganggu yang sebenarnyaInclude
Mohsen Afshin