Итак, у вас есть две таблицы: Experiment
и ExperimentType
. Между этими двумя существует отношение «многие ко многим»: каждый Experiment
является экспериментом с нулем или более ExperimentTypes
; каждый ExperimentType
является типом ноль или более Experiments
.
Это многие ко многим можно увидеть в определениях вашего класса. virtual ICollection<...>
с обеих сторон указывает на отношение «многие ко многим».
В реляционных базах данных это отношение «многие ко многим» реализуется с помощью таблицы соединений. Однако в структуре сущностей вы редко видите таблицу соединений. Он находится в вашей базе данных, однако вы не можете получить к нему доступ, используя ваш DbContext
Но как мне выполнить соединение экспериментов
ExperimentTypes, если я не могу получить доступ к распределительной таблице?
Что ж, медведь Пух должен вернуться к своей мыслительной точке. Он не хочет присоединяться к столам, он хочет, чтобы все (или некоторые) Experiments
, каждый со всеми (или некоторыми) его ExperimentTypes
.
Так почему бы просто не выполнить запрос, используя ICollection<...>
?
var experiments = myDbContext.Experiments
.Where(experiment => ...) // only if you don't want all experiments
.Select(experiment => new
{ // Select only the properties you actually plan to use
Id = experiment.Id,
Name = experiment.Name,
...
// get all or some of its ExperimentTypes
ExperimentTypes = experiment.ExperimentTypes
.Where(experimentType => ...) // only if you don't want all experiment types
.Select(experimentType => new
{
// again: select only the properties you plan to use
Id = experimentType.Id,
...
})
.ToList(),
});
Платформа сущностей знает «многие ко многим», она знает, что для этого необходимо тройное соединение с таблицей соединений, и будет выполнять это тройное соединение.
Внутренне это будет GroupJoin , вы получите Experiments
, каждый со своими ExperimentTypes
. Вы даже получаете Эксперименты, которые еще не имеют ExperimentType.
Если вы действительно хотите inner join
, вам придется сгладить эксперименты с их типами экспериментов. Это делается с использованием перегрузки для SelectMany, в которой в качестве параметра
используется resultSelector.
// flatten the Experiments with their experimentTypes
var flatInnerJoin = myDbContext.Experiments.SelectMany(experiment => experiment.ExperimentTypes,
// from each experiment and one of its experimentTypes make one new object
(experiment, experimentType) => new
{
ExperimentId = experiment.Id,
ExperimentTypeId = experimentType.Id,
...
});
})
Нет, лучше! Таким образом, вы не получите эксперименты, которые не имеют ExperimentTypes, как в стандартном внутреннем объединении.