6

Я пытаюсь выполнить поиск db с использованием кода EF5. Основные отношения структуры и таблицы заключаются в следующем:Entity Framework. Вложенные в .Include

public partial class Member 
{ 
    public int RecordID {get; set;} 
    public string Name  {get; set;} 
    ...etc. 
    public virtual ICollection<MemberLink> MasterLinks {get; set;} 
    public virtual ICollection<MemberLink> SlaveLinks {get; set;} 
    public virtual ICollection<Message> ReceivedMessages {get; set;} 
    public virtual ICollection<Message> SentMessages {get; set;} 
} 

public partial class MemberLink 
{ 
    public int   RecordID  {get; set;} 
    public virtual Member MasterMember {get; set;} 
    public virtual Member SlaveMember {get; set;} 
    ...etc. 
} 

public partial class Message 
{ 
    public int   RecordID {get; set;} 
    public virtual Member Sender {get; set;} 
    public virtual Member Recipient {get; set;} 
    ...etc. 
} 

Теперь запрос я пытаюсь выполнить, используя MemberLinkRepository и выглядит;

public IList<MemberLink> GetMasterLinks(int p_MemberID) 
{ 
    return Get() 
      .Include (memberLink => memberLink.MasterMember) 
      .Include (memberLink => memberLink.SlaveMember) 
      .Include (memberLink => memberLink.MasterMember.ReceivedMessages 
         .Where(
         msg => msg.Sender.RecordID == memberLink.SlaveMember.RecordID)) 
      .Where (memberLink => memberLink.MasterMember.RecordID == p_MemberID) 
      .ToList(); 

За исключением EF, похоже, не нравится вложенное место. Я мог бы разделить это на 2 отдельных обращения к репозиториям (и, действительно, похоже, что я, возможно, должен это сделать), но в интересах сокращения звонков в db, я пытаюсь сделать это одним мазком. Кто-нибудь знает, как я могу достичь этого в одном запросе?

Надеюсь, код иллюстрирует то, что я пытаюсь сделать ... Если нет, я попытаюсь объяснить немного лучше.

ответ

17

Короткий ответ - нет, EF не позволит вам сделать это, используя Include().

Подумайте о результате, если он позволит вам это сделать: в одном случае ваш MemberLink.MasterMember.ReceivedMessages будет полностью заполнен, на другом идентично выглядящем объекте MemberLink.MasterMember.ReceivedMessages на самом деле является подмножеством сообщений! Что произойдет, если вы попытаетесь добавить в ReceivedMessages? Что делать, если добавление не соответствует фильтру? Это мешок с болью.

Ответ заключается в использовании проекции:

public IList<MemberLinkWithFiltereredMessages> GetMasterLinks(int p_MemberID) 
{ 
    return Get() 
     .Include(memberLink => memberLink.MasterMember) 
     .Include(memberLink => memberLink.SlaveMember) 
     .Where(memberLink => memberLink.MasterMember.RecordID == p_MemberID) 
     .Select(memberLink => new MemberLinkWithFilteredMessages 
     { 
      MemberLink = memberLink, 
      FilteredMessages = memberLink.MasterMember.ReceivedMessages 
       .Where(msg => msg.Sender.RecordID == memberLink.SlaveMember.RecordID) 
     }) 
     .ToList(); 
} 

То, что вы действительно делаете просят конкретной подмножестве информации, так что явно об этом.

+0

Отлично! Только то, что я искал. Согласовано; ваш вопрос о явном запросе фильтрованного подмножества - лучший подход, поэтому я буду следовать этой логике :) – user1861826

+0

@ user1861826, если он отвечает на ваш вопрос, пожалуйста, не забудьте отметить его :) –

+0

@TimothyWalters, у меня такая же проблема .. В моем случае, вложенность идет глубоко вниз по нескольким слоям, мне удалось сделать включение, которое вы указали. В SQL, который получил сгенерированный, я мог видеть, что все столбцы возвращаются с другим псевдонимом как c1, c2 что-то вроде этого. Мой вопрос заключается в том, как я могу сформировать вложенную коллекцию DTO из всех моих включений :(.. Может быть, вы можете взять сам вышеприведенный пример, поскольку мы возвращаем все столбцы без каких-либо пользовательских DTO (которые сами являются коллекцией DTO) – TechQuery

Смежные вопросы