#c# #asp.net-core
#c# #asp.net-core
Вопрос:
У меня есть следующие объекты:
- Доброволец
- Задание
- Талант
И следующие объекты объединения «многие ко многим»:
- JobVolunteer
- JobTalent
- TalentVolunteer
И работа, и доброволец обладают множеством талантов. Я хочу выполнить поиск по всем заданиям, где их таланты совпадают с талантами волонтера.
Как я могу это сделать? На данный момент я использую следующий код, но в результате я получаю все задания, которые содержат один (или более) из требуемых талантов. Я хочу находить только те задания, где доброволец обладает (по крайней мере) всеми необходимыми талантами.
public async Task<IActionResult> FindJobs(int? id)
{
if (id == null)
{
return NotFound();
}
var volunteer = await _context.Volunteers
.Include(v => v.TalentVolunteers)
.ThenInclude(v => v.Talent)
.FirstOrDefaultAsync(m => m.VolunteerID == id);
if (volunteer == null)
{
return NotFound();
}
var jobs = new List<Job>();
var talentVolunteers = new HashSet<int>(volunteer.TalentVolunteers.Select(t => t.TalentID));
foreach (var talent in _context.JobTalents)
{
if (talentVolunteers.Contains(talent.TalentID))
{
var selectedJob = _context.Jobs
.Include(t => t.JobTalents)
.ThenInclude(v => v.Talent)
.SingleOrDefault(t => t.JobID == talent.JobID);
jobs.Add(selectedJob);
}
}
var volunteersFindJobsViewModel = _mapper.Map<Volunteer, VolunteersFindJobsViewModel>(volunteer);
volunteersFindJobsViewModel.Jobs = jobs;
return View(volunteersFindJobsViewModel);
}
Ответ №1:
Первый вариант
Выберите все идентификаторы талантов для добровольца и сохраните их в списке / массиве, а затем используйте этот список в условном выражении задания
var volunteerTalentIds = _context.TalentVolunteer.Where(a=>a.VolunteerId == {yourVolunteerId}).Select(a=>a.TalentId).ToList();
var selectedJobs = _context.Jobs.Include(a=>a.JobTalents).Where(a=>a.JobTalents.All(b=>volunteerTalentIds.Contains(b.TalentId))).ToList();
Второй вариант
Выполните длинную цепочку объединений
var selectedJobs = (from job in _context.Jobs
join jobTalent in _context.JobTalents on jobTalent.JobId equals job.JobId
join volunteerTalent in _context.VolunteerTalents on jobTalent.TalentId equals volunteetTalent.TalentId
where volunteerTalent.VolunteerId = {yourVolunteerId} select job).ToList();
Комментарии:
1. Первый вариант, похоже, не работает (я думаю, вы не можете указать, где включить в ядро EF?). Я решил это, выполнив третий запрос between для идентификаторов jobTalentIds. Тем не менее, оба метода по-прежнему дают мне все задания, где только один (или более) Таланты совпадают. Я хотел бы получать только те задания, где (по крайней мере) все таланты совпадают между заданием и волонтером.
2. Вы можете использовать Where при включении, но в случае, если включенное свойство является списком, вам нужно указать пользователя
.Any
и добавить туда подзапрос для проверки, рад, что вы решили это3. Как бы вы перефразировали это с помощью . Есть ли? Ваше второе решение работает, но дает мне все задания, в которых совпадает один талант, в то время как мне нужны только задания, в которых совпадают все таланты. Есть идеи, как с этим справиться? Спасибо!
4. Я отредактировал ответ, я думаю, вот как вы это делаете, используя
.Any
5. Действительно, ваш вариант 1 теперь тоже работает. Спасибо! Единственная проблема в том, что эти решения дают мне все задания, где один талант добровольца соответствует требуемым талантам от задания. Мне бы понравились задания, в которых доброволец обладает всеми талантами, необходимыми для работы. Есть идеи, как с этим справиться?