Кажется, что между учениками и языками существует связь «многие ко многим»: каждый ученик говорит на ноль или более языков, а на каждом языке говорит ноль или более учеников.
Если вы выполнили Условные обозначения Entity Framework , у вас будет что-то похожее на это:
class Student
{
public int Id {get; set;}
... // other properties
// Every student speaks zero or more Languages (many-to-many)
public virtual ICollection<Language> Languages {get; set;}
}
class Language
{
public int Id {get; set;}
... // other properties
// Every Language is spoken by zero or more Students(many-to-many)
public virtual ICollection<Student> Students {get; set;}
}
Для полноты Dbcontext:
class MyDbContext : DbContext
{
public DbSet<Student> Students {get; set;}
public DbSet<Language> Languages {get; set;}
}
Поскольку вы придерживались соглашений, структура сущности обнаруживает отношение «многие ко многим». Вам не нужно указывать соединительную таблицу для этого, вместо этого вы можете использовать virtual ICollection
.
Дайте мне всех учеников, которые говорят по крайней мере на всех языках в объекте LangIds
Всякий раз, когда вы хотите проверить, содержит ли коллекция A хотя бы все элементы из коллекции B, рассмотрите возможность проверки B.Except(A).Any()
. Если это правда, то, очевидно, некоторые элементы из B не находятся в A.
Так что, если LangIds.Except(Student.Languages).Any()
верно, то вы знаете, что есть языки, на которых ученик не говорит. Вы не хотите этого ученика. Вам нужны только те ученики, у которых Any приводит к ложному результату.
Как только вы это узнаете, код очень прост:
var result = dbContext.Students
.Where(student => !langIds.Except(student.Languages).Any() // note the "!"
.ToList();
Это, вероятно, принесет больше свойств, чем вы на самом деле планируете используйте, поэтому рассмотрите возможность добавить Select:
var result = dbContext.Students
.Where(student => !langIds.Except(student.Languages).Any()
.Select(student => new
{
// Select only the Student properties that you plan to use
Id = student.Id,
Name = student.Name,
...
// Only if you plan to use all languages that the Student speaks:
Languages = student.Languages.Select(language => new
{
// again: only the language properties that you plan to use:
Id = language.Id,
Code = language.Code,
Abbreviation = language.Abbreviation,
...
// no need to fill language.Students
})
.ToList(),
});