Включіть кілька посилань на другому рівні


88

Припустимо, у нас є така модель:

public class Tiers
{
    public List<Contact> Contacts { get; set; }
}

і

public class Contact
{
    public int Id { get; set; }
    public Tiers Tiers { get; set; }
    public Titre Titre { get; set; }
    public TypeContact TypeContact { get; set; }
    public Langue Langue { get; set; }
    public Fonction Fonction { get; set; }
    public Service Service { get; set; }
    public StatutMail StatutMail { get; set; }
}

За допомогою EF7 я хотів би отримати всі дані з таблиці Tiers, з таблиці Contact, таблиці Titre, таблиці TypeContact тощо ... за допомогою однієї єдиної інструкції. За допомогою API Include / ThenInclude я можу написати щось подібне:

_dbSet
     .Include(tiers => tiers.Contacts)
          .ThenInclude(contact => contact.Titre)
     .ToList();

Але після властивості Titre я не можу включити інші посилання, такі як TypeContact, Langue, Fonction ... Метод Include пропонує об'єкти Tiers, а ThenInclude - об'єкт Titre, але не об'єкт Contact. Як я можу включити всі посилання зі свого списку контактів? Чи можемо ми досягти цього за допомогою однієї єдиної інструкції?

Відповіді:


154

.ThenInclude()буде ланцюгом або останнього, .ThenInclude()або останнього .Include()(залежно від того, що пізніше), щоб взяти кілька рівнів. Щоб включити кількох братів і сестер на одному рівні, просто використовуйте інший .Include()ланцюжок. Правильне форматування коду може значно покращити читабельність.

_dbSet
    .Include(tiers => tiers.Contacts).ThenInclude(contact => contact.Titre)
    .Include(tiers => tiers.Contacts).ThenInclude(contact => contact.TypeContact)
    .Include(tiers => tiers.Contacts).ThenInclude(contact => contact.Langue);
    // etc.

3
До речі, це питання надихнуло мене на створення випуску № 2124
bricelam

чому ні: var contacts = _dbSet.Include(tiers => tiers.Contacts); contacts.ThenInclude(contact => contact.Titre); contacts.ThenInclude(contact => contact.TypeContact); contacts.ThenInclude(contact => contact.Langue); чи це не спрацює?
Даг,

1
@Doug Ні, ти створював би Queryableкожен раз нові об’єкти і ніколи їх не оцінював . contactsматиме лише оригінальне значення, яке ви йому призначили.
bricelam

що якщо tiers.Contactsце List<T>? як би ви вказали пункт тоді?
shashwat 02

2
Це рішення працює, але отриманий оператор SQL призводить до трьох ЛІВИХ ПРИЄДНАНЬ з контактами (принаймні, на мій досвід). Це страшенно неефективно. Повинен бути кращий спосіб.
EL MOJO

7

Для повноти:

Також можна включити вкладені властивості безпосередньо через, Include якщо вони не є властивостями колекції так:

_dbSet
    .Include(tier => tier.Contact.Titre)
    .Include(tier => tier.Contact.TypeContact)
    .Include(tier => tier.Contact.Langue);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.