Khung thực thể - Bao gồm nhiều cấp thuộc tính


376

Phương thức Bao gồm () hoạt động khá tốt cho Danh sách trên các đối tượng. Nhưng nếu tôi cần đi sâu hai cấp thì sao? Ví dụ: phương thức bên dưới sẽ trả về ApplicationServers với các thuộc tính được bao gồm ở đây. Tuy nhiên, ApplicationWithOverridegroup là một thùng chứa khác chứa các đối tượng phức tạp khác. Tôi có thể thực hiện Bao gồm () trên tài sản đó không? Hoặc làm thế nào tôi có thể tải tài sản đó đầy đủ?

Hiện tại, phương pháp này:

public IEnumerable<ApplicationServer> GetAll()
{
    return this.Database.ApplicationServers
        .Include(x => x.ApplicationsWithOverrideGroup)                
        .Include(x => x.ApplicationWithGroupToForceInstallList)
        .Include(x => x.CustomVariableGroups)                
        .ToList();
}

Sẽ chỉ cư trú thuộc tính Kích hoạt (bên dưới) chứ không phải thuộc tính Ứng dụng hoặc CustomVariablegroup (bên dưới). Làm thế nào để tôi thực hiện điều này xảy ra?

public class ApplicationWithOverrideVariableGroup : EntityBase
{
    public bool Enabled { get; set; }
    public Application Application { get; set; }
    public CustomVariableGroup CustomVariableGroup { get; set; }
}

Xin chào, Tại sao tôi nhận được một ngoại lệ Expression must be a member expressionkhi tôi thử điều này: Để bao gồm một bộ sưu tập và sau đó một bộ sưu tập giảm một cấp : query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection)).
Joe.wang

1
@BobHorn, tôi có cùng một vấn đề .. Trong trường hợp của tôi, việc lồng vào sâu xuống nhiều lớp, tôi đã quản lý để thực hiện bao gồm bạn chỉ ra. Trong SQL được tạo, tôi có thể thấy tất cả các cột đang trả về với tên bí danh khác nhau là c1, c2 giống như vậy. Câu hỏi của tôi là, làm thế nào tôi có thể tạo thành một bộ sưu tập DTO lồng nhau trong số tất cả bao gồm :( .. Có thể bạn có thể lấy ví dụ trên, trong đó chúng tôi sẽ trả lại tất cả các cột mà không có bất kỳ DTO tùy chỉnh nào (mà chính nó là bộ sưu tập của DTO )
TechQuery

Câu trả lời:


704

Đối với EF 6

using System.Data.Entity;

query.Include(x => x.Collection.Select(y => y.Property))

Hãy chắc chắn để thêm using System.Data.Entity;để có được phiên bản Includemất trong lambda.


Đối với lõi EF

Sử dụng phương pháp mới ThenInclude

query.Include(x => x.Collection)
     .ThenInclude(x => x.Property);

1
Tôi không thể thực hiện Bao gồm () trên Ứng dụngWithOverridegroup. Nó không xuất hiện trong intellisense.
Bob Horn

Tôi không thể sử dụng chỉnh sửa của bạn vì ApplicationWithOverridegroup là một Danh sách. Ứng dụng là một thuộc tính trên mỗi mục trong danh sách, không phải trên danh sách.
Bob Horn

1
Ahhhh, nhưng liên kết mà bạn cung cấp dường như cung cấp câu trả lời. Hãy để tôi thử điều này: Để bao gồm một bộ sưu tập và sau đó một bộ sưu tập xuống một cấp: query.Include (e => e.Level1Collection.Select (l1 => l1.Level2Collection)).
Bob Horn

60
Hãy nhớ bao gồm System.Data.Entity trong các ứng dụng. Nếu không, Intellisense sẽ chỉ cung cấp cho bạn phiên bản Bao gồm (đường dẫn chuỗi) của phương thức.
OJ Raqueño

5
@Adeem bạn cần gọi Includecho từng tài sản:Db.States.Include(state => state.Cities.Select(city => city.Customers).Include(state => state.Cities.Select(city => city.Vendors)
Diego Torres

72

Nếu tôi hiểu bạn chính xác, bạn đang hỏi về việc bao gồm các thuộc tính lồng nhau. Nếu vậy :

.Include(x => x.ApplicationsWithOverrideGroup.NestedProp)

hoặc là

.Include("ApplicationsWithOverrideGroup.NestedProp")  

hoặc là

.Include($"{nameof(ApplicationsWithOverrideGroup)}.{nameof(NestedProp)}")  

6
Cảm ơn, tôi có thể thử nó. Tôi đã hy vọng có thể giữ cho mọi thứ được gõ mạnh mẽ và tránh các chuỗi ký tự. Nhưng nếu đó là cách nó phải được thực hiện ...
Bob Horn

1
Bạn đã gần. Tôi có thể không rõ ràng rằng ApplicationWithOverridegroup là một danh sách. Cảm ơn đã giúp đỡ!
Bob Horn

@Judo, tôi có cùng một vấn đề .. Trong trường hợp của tôi, việc lồng vào sâu xuống nhiều lớp, tôi đã quản lý để thực hiện một bao gồm bạn chỉ ra. Trong SQL được tạo, tôi có thể thấy tất cả các cột đang trả về với tên bí danh khác nhau là c1, c2 giống như vậy. Câu hỏi của tôi là, làm thế nào tôi có thể tạo thành một bộ sưu tập DTO lồng nhau trong số tất cả bao gồm :( .. Có thể bạn có thể lấy ví dụ trên, trong đó chúng tôi sẽ trả lại tất cả các cột mà không có bất kỳ DTO tùy chỉnh nào (mà chính nó là bộ sưu tập của DTO )
TechQuery

2
Hãy nhớ bao gồm System.Data.Entity trong các ứng dụng. Nếu không, Intellisense sẽ chỉ cung cấp cho bạn Include(string path)phiên bản của phương thức.
AlexMelw

52

EF Core: Sử dụng "ThenInclude" để tải các cấp độ đột biến: Ví dụ:

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

53
Có vẻ như đây chỉ là EF Core
Chris Marisic

27
FYI: VS2017, intellisense không hoạt động cho .ThenInclude. Chỉ cần nhập nó theo cách bạn nghĩ nó nên và đánh dấu lỗi sẽ biến mất.
JohnWlingsby

4
Tôi muốn nhấn mạnh nhận xét của @JohnWrenby, Intellisense đôi khi có thể mất nhiều thời gian để xử lý các ThenInclude này, điều này có thể gây nhầm lẫn cho người dùng mới. Tôi cũng có trường hợp biểu thức Bao gồm lambda đơn giản không được xử lý đúng cách, cho đến khi bạn chỉ cần nhập và biên dịch nó, bỏ qua các "lỗi" được hiển thị trong VS.
Pac0

@ Pac0 bạn đã cứu ngày của tôi. đấu tranh để xem các mục trẻ em và không thể.
Bendram

28

Tôi đã tạo một trình trợ giúp nhỏ cho Entity Framework 6 (kiểu .Net Core), để bao gồm các thực thể phụ một cách tốt đẹp.

Nó hiện có trên NuGet: Cài đặt-Gói ThenInclude.EF6

using System.Data.Entity;

var thenInclude = context.One.Include(x => x.Twoes)
    .ThenInclude(x=> x.Threes)
    .ThenInclude(x=> x.Fours)
    .ThenInclude(x=> x.Fives)
    .ThenInclude(x => x.Sixes)
    .Include(x=> x.Other)
    .ToList();

Gói có sẵn trên GitHub .


xin chào, tôi có một ngoại lệ trong thời gian chạy, không thể chuyển từ Có thể truy cập <có thể quan sát được> sang có thể truy cập <genericcollection>
user2475096

Tôi đang sử dụng db trước tiên và tôi đã sửa đổi tệp tt để có được ObservableCollections cho tất cả các thực thể của mình, mọi sự trợ giúp đều được chào đón.
dùng2475096

2
@ lenny32 bất cứ điều gì cần biết với phần mở rộng này?
Aaron Hudon

Lưu ý rằng điều này là không bắt buộc nếu thuộc tính bạn điều hướng là một đối một với Dbset mà bạn đã điều hướng và bạn có thể xâu chuỗi DbSet<One>().Include(x => x.Two.Three.Four.Five.Six)với nhược điểm duy nhất là bạn đang tính toán một sản phẩm cartesian và có khả năng tăng băng thông.
John Zabroski

23

Các ví dụ EFCore khác trên MSDN cho thấy bạn có thể thực hiện một số điều khá phức tạp với IncludeThenInclude .

Đây là một ví dụ tốt về mức độ phức tạp mà bạn có thể nhận được (đây là tất cả một tuyên bố!):

viewModel.Instructors = await _context.Instructors

      .Include(i => i.OfficeAssignment)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Enrollments)
                .ThenInclude(i => i.Student)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Department)

      .AsNoTracking()
      .OrderBy(i => i.LastName)
      .ToListAsync();

Xem cách bạn có thể xâu chuỗi Includengay cả sau ThenIncludeđó và loại 'đặt lại' bạn trở lại cấp độ của thực thể cấp cao nhất (Giảng viên).

Bạn thậm chí có thể lặp lại cùng một bộ sưu tập 'cấp độ đầu tiên' (CourseAssignments) nhiều lần theo sau bởi ThenIncludescác lệnh riêng biệt để đến các thực thể con khác nhau.

Lưu ý truy vấn thực tế của bạn phải được gắn thẻ vào cuối Includehoặc ThenIncludeschuỗi. Những điều sau đây KHÔNG hoạt động:

var query = _context.Instructors.AsQueryable();
query.Include(i => i.OfficeAssignment);

var first10Instructors = query.Take(10).ToArray();

Chúng tôi thực sự khuyên bạn nên thiết lập ghi nhật ký và đảm bảo các truy vấn của bạn không nằm ngoài tầm kiểm soát nếu bạn bao gồm nhiều hơn một hoặc hai điều. Điều quan trọng là phải xem cách nó thực sự hoạt động - và bạn sẽ nhận thấy mỗi 'bao gồm' riêng biệt thường là một truy vấn mới để tránh các phép nối lớn trả về dữ liệu dư thừa.

AsNoTracking rất có thể tăng tốc mọi thứ nếu bạn không có ý định thực sự chỉnh sửa các thực thể và lưu lại.


Có cách nào để có được cả Ghi danh và các Phòng ban mà không cần lặp đi lặp lại. Bao gồm khóa học và khóa học không? (Cho đến nay, có vẻ như Api có thể tiến sâu hơn với .ThenInclude, hoặc trở lại cấp cao nhất với .Include, nhưng không có gì để ở cùng cấp độ?)
William Jockusch 8/2/18

Nếu bạn muốn tải nhanh, hãy theo dõi các blog của EF Core 2.1.msdn.microsoft.com/dotnet/2018/02/02/, nhưng nếu bạn chỉ muốn tải thêm ở cùng cấp thì tôi nghĩ đây là do thiết kế. Tôi không chắc bạn đang nghĩ gì - nó không đòi hỏi nhiều hơn để làm điều này và nó làm giảm đáng kể những gì quay trở lại từ cơ sở dữ liệu. Một thực thể có thể chỉ có một hoặc hai thứ 'cùng cấp' nhưng nó cũng có thể có 50 cho một dự án lớn, rõ ràng làm cho ứng dụng của bạn nhanh hơn nhiều.
Simon_Weaver

Đây là một lời giải thích tốt về khái niệm Bao gồm "đặt lại" mức trở lại mức ban đầu một lần nữa. Giúp tôi quấn đầu quanh chế độ bá đạo của hệ thống. Chúc mừng!
AFM-Horizon

22

Tôi cũng đã phải sử dụng nhiều bao gồm và ở cấp 3 tôi cần nhiều thuộc tính

(from e in context.JobCategorySet
                      where e.Id == id &&
                            e.AgencyId == agencyId
                      select e)
                      .Include(x => x.JobCategorySkillDetails)
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.DurationType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RuleType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RateType))
                      .FirstOrDefaultAsync();

Điều này có thể giúp ai đó :)


1
điều này có thể được thực hiện mà không cần lặp lại.Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt......
Multinerd

điều đó còn tùy thuộc, bạn muốn đi sâu đến đâu
dnxit

7

Hãy để tôi nói rõ rằng bạn có thể sử dụng quá tải chuỗi để bao gồm các mức lồng nhau bất kể bội số của các mối quan hệ tương ứng, nếu bạn không phiền khi sử dụng chuỗi ký tự:

query.Include("Collection.Property")

1
Phương pháp này rất hữu ích cho tôi để tìm hiểu làm thế nào điều này có thể được mã hóa trong VB, vì tôi không thể tìm thấy bất cứ nơi nào sau nhiều giờ làm việc.
Coder

Điều này làm việc rất tốt cho tôi, tôi sử dụng nó rất nhiều !!! Nó thậm chí hoạt động kết hợp với các câu lệnh .SelectMany:query.SelectMany(x=>x.foos).Include("bar").Include("bar.docs")...
Ephie
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.