2011-12-08 41 views
6

Nếu tôi có một truy vấn mà trông như thế này:Entity Framework bao gồm đâu

var forms = repo.GetForms().Where(f => f.SubForms.Any(sf => sf.Classes.Any(c => c.TermId == termId))); 

Từ đây bạn có thể thấy sơ đồ của tôi là như sau:

SubForm có nhiều Class trong đó có nhiều Term.

Những gì tôi muốn:

Tất cả SubForms với Classes của họ Trong một đặc biệt Term.

Điều đang xảy ra bây giờ là tôi nhận được tất cả SubForm có bất kỳ Class nào trong một số Term cụ thể. Điều đó có nghĩa là SubForm quay lại với TẤT CẢ trẻ em Class và không chỉ những cái có liên quan đến Term.

Ví dụ: Tôi có 2 thuật ngữ, một biểu mẫu con với 2 lớp trong mỗi học kỳ. Truy vấn này mang về 4 lớp thay vì 2 trong thuật ngữ cụ thể đó.

Có bất kỳ Include('Expression') nào tôi có thể sử dụng để nói rằng tôi chỉ muốn bao gồm tất cả các lớp dựa trên điều kiện không? Hoặc là truy vấn của tôi sai?

+0

'Bất kỳ' đầu tiên được coi là 'Where', đúng không? Nếu không, truy vấn của bạn sẽ chỉ trả về một 'bool', nói rằng" Có bất kỳ biểu mẫu con nào có các lớp với các thuật ngữ với termId đã cho, có hoặc không? " – Slauma

+0

@ Slauma Xin lỗi, đó cũng là một cấp độ khác trên biểu thức đó, tôi sẽ chỉnh sửa nó, xin lỗi –

Trả lời

0

Tôi không biết tên chính xác của các mối quan hệ, nhưng nó phải là một cái gì đó dọc theo dòng của

repo.Terms 
    .Include("Classes") 
    .Include("Classes.SubForms") 
    .SingleOrDefault(x => x.TermId = termId); 

// or 

repo.GetSubForms 
    .Include("Classes") 
    .Where(sf => sf.Classes.Where(c => c.TermId == termId)); 
4

Một Include(Where Expression) không tồn tại. Nếu bạn sử dụng tải mong muốn với Bao gồm bạn sẽ luôn luôn tải tất cả các yếu tố.

Có một cách để giải quyết vấn đề này bằng cách sử dụng phép chiếu. Ý tưởng cơ bản là bạn sẽ chọn một loại vô danh mới với thuộc tính bạn muốn và một thuộc tính khác với các mục điều hướng được lọc. EF sẽ liên kết chúng với nhau và kết quả là bạn sẽ giả mạo một số Include(Where ...)

Check this for an example.

+1

Nitơ nhỏ: 'Bao gồm (Biểu thức)' không tồn tại như phương thức mở rộng System.Data.Entity.DbExtensions.Include, nhưng có ý nghĩa hoàn toàn khác. Nó được sử dụng như là một thay thế cho các chuỗi ký tự: 'repo.Terms.Include (term => term.Classes)'. – hvd

+0

Thnx. Tôi đã sửa đổi câu trả lời của tôi –

0

Điều này có vẻ là một yêu cầu chung, thật khó để tìm ra giải pháp cho nó khi tôi nhìn vào đầu năm nay. Tôi đã kết thúc bằng cách sử dụng các giải pháp bao gồm trong liên kết dưới đây (Tôi không chắc chắn đây là giải pháp chính xác tôi tìm thấy, nhưng nó là cùng một ý tưởng). Hi vọng điêu nay co ich!

Filter the "Includes" table on Entity Framework query

   //Found this method to filter our child objects instead of using .include() 
       var Results = (from res in 
            (from u in DataContext.User 
            where u.Type.ToUpper() != "ADMIN" 
            && u.StartDate <= DateTime.Now 
            && (u.EndDate == null || u.EndDate >= DateTime.Now) 
            select new 
            { 
             User = u, 
             Access = u.Access.Where(a => a.StartDate <= DateTime.Now 
                && (a.EndDate == null || a.EndDate >= DateTime.Now)) 
            } 
            ) 
           select res); 

       //The ToArray is neccesary otherwise the Access is not populated in the Users 
       ReturnValue = Results.ToArray().Select(x => x.User).ToList(); 
6

Sử dụng này:

var subForms = repo.GetSubForms.Select(sf = new { 
     SubForm = sf, 
     Classes = sf.Classes.Where(c => c.TermId == termId) 
    }).ToList() 
    .Select(t => t.SubForm) 
    .ToList(); 

UPDATE: dựa trên @ bình luận Slauma của:

Nếu bạn muốn tải SubForm s rằng họ có bất kỳ Class có a Term bởi termId, bạn có thể đi từ cuối để bắt đầu; như thế này:

var subForms = repo.Terms.Where(t => t.Id == termId).Select(t => new { 
     Term = t, 
     Class = t.Class, 
     SubForm = t.Class.SubForm 
    }).ToList() 
    .Select(t => t.SubForm).ToList(); 

HOẶC theo một cách đơn giản nhất, bạn có thể sử dụng Include trên Term bạn, hãy xem:

var subForms = repo.Terms.Include("Class.SubForm").Where(t => t.Id == termId) 
        .Select(t => t.Class.SubForm).ToList(); 

LƯU Ý: Như tôi có thể hiểu được từ câu hỏi của bạn, bạn có một mối quan hệ như thế này:

SubForm has_many Class has_many Term 

Nhưng mã bạn đã cung cấp đang hiển thị elationship như thế này:

SubForm has_many Class 
Term has_many Class 

Nếu bạn có thể, hãy đặt thực thể của bạn hoặc giải thích mối quan hệ của họ. Cảm ơn bạn.

+1

Bạn vẫn cần bộ lọc giữa 'GetSubForms' và' Select': 'Where (sf => sf.Classes.Any (c => c.TermId == termId))'. Nếu không, bạn sẽ tải * tất cả * các biểu mẫu con từ DB, bao gồm các biểu mẫu con với các lớp không có termId phù hợp. – Slauma

+0

@Slauma OK, thực sự tôi không hiểu câu hỏi hoàn toàn; Vì vậy, tôi cập nhật câu trả lời của tôi; Cảm ơn bạn :) –

+1

Đúng, «Bất kỳ' đầu tiên trong câu hỏi là khó hiểu. Tôi vừa viết bình luận dưới câu hỏi bởi vì tôi tin rằng anh ta thực sự là một 'Where'. – Slauma

1

Bạn biết đôi khi tôi bắt đầu bị lạc trong các phương pháp mở rộng LINQ ưa thích và cố gắng tìm ra cách háo hức tải chính xác những gì tôi muốn và đến một khái niệm "tham gia" rất đơn giản.

var result = 
(from f in SubForums 
from c in Classes 
from t in Term 
where t.TermId = 1 
select new { SubForum = f, Class = c, Term = t }).ToList(); 

Đây là liên kết đơn giản sử dụng các thuộc tính điều hướng được xác định trước (do đó bạn không phải chỉ định điều kiện tham gia). Bạn trả về một kiểu ẩn danh với mọi thứ bạn cần. Vẻ đẹp của việc này là Entity Framework sẽ thực hiện tự động sửa lỗi cho bạn, do đó bạn được tự do trả lại SubForum chỉ từ phương thức của bạn nếu bạn muốn, nó sẽ tự động chứa tham chiếu Lớp và các tham chiếu Term tiếp theo.

Các vấn đề liên quan