Я собираюсь игнорировать свойства virtual
в вашем классе InitialTrainingAssociation
, так как вы ничего о них не упомянули, и мне не сразу понятно, содержат ли они данные или почему они virtual
.
Кажется, IQueryable.Join
- это самый простой способ объединить нужные данные.
В следующем примере мы начнем с записей из таблицы InitialTrainings.Затем мы будем Join
с таблицей InitialTrainingAssociations, что приведет к коллекции парных объектов InitialTraining и InitialTrainingAssociation.
var initialTrainingResults =
// Start with the InitialTrainings data.
db.InitialTrainings
// Add association information.
.Join(
// The table we want to join with
db.InitialTrainingAssociations,
// Key selector for the outer type (the type of the collection
// initiating the join, in this case InitialTraining)
it => it.Id,
// Key selector for the inner type (the type of the collection
// being joined with, in this case InitialTrainingAssociation)
ita => ita.InitialTrainingId,
// Result selector. This defines how we store the joined data.
// We store the results in an anonymous type, so that we can
// use the intermediate data without having to declare a new class.
(InitialTraining, InitialTrainingAssociation) =>
new { InitialTraining, InitialTrainingAssociation }
)
Отсюда мы можем добавлять данные из таблиц PerformanceAnchors и GradingSystems, выполняя большеJoin
s.Каждый раз, когда мы выполняем Join
, мы добавляем новую сущность к нашему анонимному типу.Результатом будет коллекция анонимных типов, представляющих данные, которые мы извлекли из базы данных.
// Add performance anchor information.
.Join(
db.PerformanceAnchors,
x => x.InitialTrainingAssociation.PerformanceAnchorId,
pa => pa.Id,
(x, PerformanceAnchor) =>
new { x.InitialTrainingAssociation, x.InitialTraining, PerformanceAnchor }
)
// Add grading system information.
.Join(
db.GradingSystems,
x => x.InitialTrainingAssociation.GradingSystemId,
gs => gs.Id,
// No need for InitialTrainingAssociation anymore, so we don't
// include it in this final selector.
(x, GradingSystem) =>
new { x.InitialTraining, x.PerformanceAnchor, GradingSystem }
);
(Это был подробный пример, показывающий, как вы можете объединить все таблицы вместе. Вы можете использовать меньшеПрисоединяется, если вам не нужен доступ ко всем данным одновременно, и вы можете отфильтровать коллекцию InitialTrainings, с которой мы начинаем, если вы знаете, что вам нужен только доступ к определенным частям данных.)
На этом этапе initialTrainingResults
- это IEnumerable
, содержащий одну запись для каждой ассоциации между таблицами InitialTrainings, PerformanceAnchors и GradingSystems.По сути, все, что мы сделали, взяли все InitialTrainingAssociations и расширили их идентификаторы до реальных объектов.
Чтобы получить самый последний набор данных для каждого якоря производительности:
var performanceAnchors = initialTrainingResults
// Group by each unique Performance Anchor. Remember, the IEnumerable
// we are operating on contains our anonymous type of combined Training,
// Performance Anchor and Grading data.
.GroupBy(x => x.PerformanceAnchor.Id)
// Order each Performance Anchor group by the dates of its training,
// and take the first one from each group
.Select(g => g.OrderByDescending(x => x.InitialTraining.DateTakenInitial).First());