Включить вложенные объекты, используя LINQ - PullRequest
20 голосов
/ 24 августа 2011

Я первый раз возлюсь с LINQ и сначала использую код EF 4.1.

У меня есть сущности, содержащие вложенные списки других сущностей, например:

class Release
{
    int ReleaseID { get; set; }
    string Title { get; set; }
    ICollection<OriginalTrack> OriginalTracks { get; set; }
}

class OriginalTrack
{
    int OriginalTrackID { get; set; }
    string Title { get; set; }
    ICollection<Release> Releases { get; set; }
    ICollection<OriginalArtist> OriginalArtists { get; set; }
}

class OriginalArtist
{
    int OriginalArtistID { get; set; }
    string Name { get; set; }
    ICollection<OriginalTrack> OriginalTracks { get; set; }
}

Мне интересно, как быстрее всего одним запросом LINQ получить всю информацию, где ReleaseID == some value.

Я сделал свою домашнюю работу, но нашел решения, которые требуют неявного восстановления объекта (обычно анонимного) с требуемыми данными. Я хочу получить данные из базы данных в точном формате, в котором они хранятся в базе данных, то есть при извлечении объекта Release с соответствующим ReleaseID извлекает и заполняет все данные OriginalTrack и OriginalArtist в списках.

Я знаю о Include(), но не знаю, как применить его для нескольких сущностей.

Вся помощь очень ценится.

Ответы [ 3 ]

14 голосов
/ 25 августа 2011

Используйте Include. Это цель Include, и нет причин писать кучу вложенных операторов выбора.

context.Releases.Include("OriginalTracks.OriginalArtist")
    .Where(release => release.ReleaseID == id);

Это проще для написания, проще для чтения и сохраняет существующую структуру данных.

Чтобы использовать Include, вам необходимо указать имя свойства, которое вы хотите вернуть - это означает, что имя существует в вашем коде, а не в базе данных. Например:

  • .Include("OriginalTracks") будет включать свойство OriginalTracks в каждом выпуске
  • .Include("OriginalTracks.OriginalArtist") будет включать свойство OriginalTracks в каждом выпуске и OriginalArtist в каждом треке ( обратите внимание, что невозможно - синтаксически или логически - включить OriginalArtist в том числе OriginalTrack )
  • .Include("OriginalTracks").Include("OtherProperty") будет включать объекты OriginalTracks и OtherProperty в каждом выпуске.

Вы можете связать столько, сколько хотите, например:

.Include("Tracks.Artist").Include("AnotherProperty")
    .Include("ThirdProperty.SomeItems").Where(r => r.something);

совершенно верно. Единственное требование состоит в том, чтобы вы поставили Include на EntitySet, а не на запрос - вы не можете .Where().Include().

10 голосов
/ 25 августа 2011

Не беспокойтесь об использовании include здесь

просто сделайте что-то вроде следующего

var query = 
    from release in ctx.Releases
    select new {
        release,
        originalTracks = from track in release.OriginalTracks
                         select new {
                               track,
                               releases = track.Releases,
                               orignialArtist = from artist in track.OriginalArtists
                                                select new {
                                                     artist,
                                                     artist.OriginalTracks
                                                }
                         }
        }

var Releases = query.Select(x => x.Release);

Должен загрузить все ваши данные

Я работал с информацией из этогопост здесь.

http://blogs.msdn.com/b/alexj/archive/2009/10/13/tip-37-how-to-do-a-conditional-include.aspx

9 голосов
/ 12 января 2014

Чтобы включить вложенные объекты без использования строковых литералов, используйте Select, например:

context.Releases.Include(r => r.OriginalTracks.Select(t => t.OriginalArtist))
    .Where(release => release.ReleaseID == id);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...