Вложенный Где на 1-ко-многим в LINQ2Entity - PullRequest
0 голосов
/ 11 марта 2012

Я использую EF4. Имея 2 лица: Персона {Имя} Hobbys {Person.Name, IsCoolHobby} 1 человек может иметь несколько хобби.

Теперь у меня есть

IQueryable<Person> p;
p = container.PersonSet.Include("Hobbys").AsQueryable();
p = p.Where(x => x ?????);
List<Person> tmp = p.ToList();

Как я могу вернуть только тех людей, у которых есть классное хобби (IsCoolHobby == true)? Я попытался присоединиться, но я не смог загрузить их в список (выбор может вернуть только Персона, Хобби или новый Тип - но как снова сопоставить их с объектами сущностей?)

Спасибо

1 Ответ

2 голосов
/ 11 марта 2012

Как я могу вернуть только тех людей, у которых есть классное хобби (IsCoolHobby == true)?

List<Person> tmp = container.PersonSet.Include("Hobbys")
    .Where(p => p.Hobbys.Any(h => h.IsCoolHobby))
    .ToList();

Это загрузит людей, у которых есть хотя бы одно классное хобби, кромеHobbys коллекция для этих людей всегда будет содержать все хобби, а также неохлаждаемые хобби.

Редактировать

К сожалению, фильтрация и сортировка детей во время желаниязагрузка (Include) в настоящее время не поддерживается.На странице предложений по функции EF для этой функции имеется запрос .Запрос имеет статус «На рассмотрении», поэтому есть небольшая надежда, что он может быть реализован в будущем.(Вероятно, far future: По крайней мере, в первых документах о EF 5 (бета) на MSDN прямо сказано, что активная загрузка с фильтрацией / сортировкой все еще не реализована.)

На данный момент есть толькодва обходных пути.Во-первых, использовать проекцию:

var projectedData = container.PersonSet
    .Where(p => p.Hobbys.Any(h => h.IsCoolHobby))
    .Select(p => new
    {
        Person = p,
        CoolHobbys = p.Hobbys.Where(h => h.IsCoolHobby)
    })
    .ToList();

В результате получается коллекция анонимных объектов, которая содержит пользователя, у которого есть классные хобби, и коллекцию этих классных хобби.Если вы не отключите отслеживание изменений (используя опцию NoTracking для запроса), коллекция хобби пользователя должна автоматически заполняться результатом.

Второй вариант - использовать «явную» загрузку с CreateSourceQuery:

List<Person> tmp = container.PersonSet
    .Where(p => p.Hobbys.Any(h => h.IsCoolHobby))
    .ToList();
foreach (var person in tmp)
{
    person.Hobbys.Attach(person.Hobbys.CreateSourceQuery()
        .Where(h => h.IsCoolHobby).ToList());
}

Здесь следует отметить две вещи:

  • CreateSourceQuery доступно только на EntityCollection с, т. Е. Если вы используете EntityObject производные сущности.Это не доступно для объектов POCO в EF 4.0.(EF> = 4.1 / DbContext имеет возможность явной загрузки также для POCO -> Query() метод.)
  • Приведенный выше код представляет 1 + N циклических переходов в базу данных: первый для коллекции сотрудниковбез хобби, а затем один дополнительный запрос на человека, чтобы загрузить классные хобби.
...