EF LINQ bao gồm nhiều thực thể và lồng nhau


155

Ok, tôi có các thực thể ba cấp độ với hệ thống phân cấp sau: Khóa học -> Mô-đun -> Chương

Đây là tuyên bố ban đầu của EF LINQ:

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

Bây giờ, tôi muốn bao gồm một thực thể khác gọi là Lab được liên kết với một khóa học.

Làm cách nào để bao gồm thực thể Lab?

Tôi đã thử cách sau nhưng không được:

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

Bất kỳ ý tưởng về bao gồm các thực thể thứ 2?

Bất kỳ lời khuyên hoặc thông tin sẽ được đánh giá cao. Cảm ơn!


1
Thêm một cái khác .Includesẽ hoạt động trừ khi bạn có nghĩa là phần bổ sung bao gồm một đứa cháu của Khóa học. Xem cái này hoặc một lựa chọn tốt hơn là cái này
von v.

Bản sao liên quan / có thể có của stackoverflow.com/q/3356541
StuartLC

Câu trả lời:


234

Bạn đã thử chỉ cần thêm một Include:

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

Giải pháp của bạn không thành công vì Includekhông sử dụng toán tử boolean

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

Cập nhật Để tìm hiểu thêm, tải xuống LinqPad và xem qua các mẫu. Tôi nghĩ đó là cách nhanh nhất để làm quen với Linq và Lambda.

Khi bắt đầu - sự khác biệt giữa SelectIncludelà với Chọn bạn quyết định những gì bạn muốn trả lại (còn gọi là phép chiếu). Bao gồm là một chức năng Tải háo hức , cho Entity Framework biết rằng bạn muốn nó bao gồm dữ liệu từ các bảng khác.

Cú pháp Bao gồm cũng có thể nằm trong chuỗi. Như thế này:

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

Nhưng các mẫu trong LinqPad giải thích điều này tốt hơn.


Cảm kích điều đó! Tôi có thể tìm hiểu thêm về điều này ở đâu? Tôi đặc biệt quan tâm đến sự khác biệt giữa Bao gồm và Chọn
AnimaSola

3
Chỉ cái này làm việc cho tôi : .Include("Module.Chapter"). Bất cứ ý tưởng tại sao điều đó sẽ được?
Jo Smo

5
@JoSmo bạn cần nhập không gian tên System.Data.Enityđể truy cập phần mở rộng. thêm thông tin ở đây
Jens Kloster

using System.Data.Entity;đã làm nó. Cảm ơn!
Jo Smo

1
được khuyến khích khi đề cập đến linqpad thông minh và mẹo sử dụng System.Data.Entity, thx Jens
Mike

38

Trong Entity Framework Core ( EF.core) bạn có thể sử dụng .ThenIncludeđể bao gồm các cấp tiếp theo.

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

Thêm thông tin: https://docs.microsoft.com/en-us/ef/core/querying/related-data

Lưu ý: Giả sử bạn cần nhiều ThenInclude()vào blog.Posts, chỉ cần lặp lại Include(blog => blog.Posts)và làm khác 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();

Trong EF.core tôi dường như không thể thực hiện .Include (i => i.Modules.Select (s => s.Ch chương)), cụ thể là .Select bên trong .Include. Bất cứ ai có thể xác nhận hoặc nói chuyện với?
ttugates

@ttugates Bạn dự định làm gì với lựa chọn này? Tôi nghĩ những gì bạn muốn làm là chính xác những gì bạn làm với ThenIncludelõi EF. Có lẽ làm một câu hỏi với một ví dụ tốt, để chúng ta có thể trả lời nó.
Nick N.

@Nick N - Truy vấn Linq khung thực thể: Cách thực hiện trên nhiều thuộc tính Nav và chọn từ thuộc tính Nav thứ 3 . Bởi vì những gì tôi chọn không phải là những gì tôi phù hợp, nên Bao gồm không cần thiết nên câu hỏi là tiếp tuyến. Câu hỏi của tôi có thể quá "hẹp" nhưng đánh giá cao bất kỳ trợ giúp.
ttugates

1
Ah. Trên thực tế, .ThenInclude () không hoạt động. Chỉ cần mãi mãi cho intellisense để hiển thị các bảng liên quan.
Chris J

23

Includelà một phần của giao diện lưu loát, vì vậy bạn có thể viết nhiều Includecâu lệnh theo sau

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

cảm kích điều đó! bạn có thể chỉ cho tôi nơi tôi có thể tìm hiểu thêm về điều này? Cảm ơn!
AnimaSola

1
Bạn có biết cú pháp là gì nếu Mô-đun có nhiều bảng bạn muốn tham gia không? Nói nó liên kết đến Chương và cái gì khác?
David Spence

Là một phần thông thạo của .Net hay đây là một thư viện cần được cài đặt?
codea

19

Bạn cũng có thể thử

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);

4
Cảm ơn - các ký hiệu dấu chấm trong chuỗi rất hữu ích
Evert

1
Điều này có thể hữu ích, nhưng, một lý do để không sử dụng điều này là dễ tái cấu trúc sau này: nếu bạn đổi tên thực thể "Chương" tại một số điểm, ví dụ khác sẽ tự động được đổi tên. Một điều nữa là các lỗi sẽ được tìm thấy sớm hơn: tại thời gian biên dịch, không phải thời gian chạy.
MGOwen

2

Người ta có thể viết một phương thức mở rộng như thế này:

    /// <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;
    }

Và sử dụng nó như thế này ngay cả trong một triển khai chung:

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

var query = context.Set<T>()
.Include(includedNavigationProperties);

Tôi đã thử câu trả lời của bạn, nhưng nó ném các ngoại lệ stackoverflow do một vòng lặp vô hạn với chính nó.
Victoria S.

1
@VictoriaS., Bạn có thể đổi tên phương thức tiện ích mở rộng để nó không can thiệp vào thực tếInclude
Mohsen Afshin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.