Линк к сущностям - как выбрать сущности с условием где их совокупность сущностей?

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

У меня есть сущность под названием "Компания", внутри которой у меня есть совокупность сущностей "Сотрудники" (один ко многим). Мне нужно получить все компании, и для каждой из них мне нужны только сотрудники, возраст которых превышает 21 год.

Я старался:

Return context.Companies.Include("Employees").Where(c => c.Employees.Where(e => e.Age > 21).Count() > 0)

Это не работает, так как дает мне всех сотрудников для каждой компании, если есть хотя бы один выше 21 (на самом деле это то же самое, что.Any())

Я старался:

Return context.Companies.Include("Employees").Select(c => New Company {  
.Id = c.Id, 
.Employees = c.Employees.Where(Function(e) e.Age > 24)
}).ToList()

Это тоже не сработало (хотя было бы идеально), но выдает следующую ошибку: Сущность или сложный тип "MyModel.Company" не могут быть созданы в запросе LINQ to Entities.

Как вы можете выбрать все мои компании, в которых для каждой из них работают сотрудники старше 21 года? На данный момент я выбираю все и на стороне клиента я фильтрую своих сотрудников, но мне не нравится это решение.

Кто-нибудь может мне помочь?


Спасибо Мортеза Манави-Параст, он сделает всю работу!

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

Я удивлен... Может быть, для следующего выпуска?


Для ясности мне нужен список компаний, поскольку я напрямую связываю результат моего запроса с сеткой данных. Для вашей информации, когда я щелкаю по строке моей таблицы данных (выбирая компанию), у меня появляется вторая таблица, в которую входят ее сотрудники (старше 21 года) из entityCollection.

3 ответа

Решение

Невозможно создать "условную загрузку" с включением в LINQ to Entities. Существует 2 обходных пути, хотя. Первый - это Filtered Projection, и он предложен Джастином, но может быть нежелателен во всех ситуациях, так как он предоставляет коллекцию объектов анонимного типа.

Второй способ называется " Два отслеживаемых запроса", который дает вам коллекцию строго типовых компаний, чьи сотрудники удовлетворяют условию, и я считаю, что это то, что вы ищете. Вот код для этого:

var companies = context.Companies.ToList();
var employees = context.Employee.Where(e => e.Age > 21);
foreach (var employee in employees) {
   companies.Single(c => c.CompanyID == employee.CompanyID).Employees.Add(employee);
}

Пожалуйста, взгляните на условную загрузку для другого примера.

Вместо того, чтобы использовать тип Компания, вы пытались выбрать новый анонимный тип:

Return context.Companies.Include("Employees").Select(c => New With {
    .Id = c.Id,
    .Employees = c.Employees.Where(Function(e) e.Age > 24)
}).ToList()

(Извините, если синтаксис немного нарушен, прошло много времени с тех пор, как я создал LINQ/ анонимные типы в VB.NET)

Возможно, вы слишком обдумываете это. Если у вас отношения Company => Employee с двусторонним отображением, то просто сделайте выбор по Employee с предложением where и включите компанию.

Return context.Employee.Include("Company").Where(e => e.Age > 21)
Другие вопросы по тегам