A partire da ora, sto cercando di creare un elenco che raggruppa in base a determinati criteri e quindi visualizzare tale elenco nella vista.
Ho due tabelle di database e una è una tabella di associazione.
Primo tavolo
public partial class InitialTraining
{
public InitialTraining()
{
InitialTrainingAssociations = new HashSet<InitialTrainingAssociation>();
}
public int Id { get; set; }
[ForeignKey("MedicInfo")]
public int TfoId { get; set; }
[ForeignKey("InstructorInfo")]
public int? InstructorId { get; set; }
[ForeignKey("PilotInfo")]
public int? PilotId { get; set; }
public DateTime DateTakenInitial { get; set; }
public decimal FlightTime { get; set; }
public bool Active { get; set; }
[StringLength(2000)]
public string Narrative { get; set; }
[Required]
[StringLength(20)]
public string TrainingType { get; set; }
[ForeignKey("CodePhase")]
public int PhaseId { get; set; }
[ForeignKey("PhaseTrainingType")]
public int PhaseTrainingTypeId { get; set; }
public string EnteredBy { get; set; }
public DateTime? EnteredDate { get; set; }
public virtual MedicInfo MedicInfo { get; set; }
public virtual MedicInfo InstructorInfo { get; set; }
public virtual MedicInfo PilotInfo { get; set; }
public virtual Code_Phase CodePhase { get; set; }
public virtual Code_PhaseTrainingType PhaseTrainingType { get; set; }
public virtual ICollection<InitialTrainingAssociation> InitialTrainingAssociations { get; set; }
}
Seconda tabella (tabella di associazione)
public class InitialTrainingAssociation
{
public int Id { get; set; }
[ForeignKey("InitialTraining")]
public int InitialTrainingId { get; set; }
[ForeignKey("CodePerformanceAnchor")]
public int? PerformanceAnchorId { get; set; }
[ForeignKey("GradingSystem")]
public int? GradingSystemId { get; set; }
public virtual AviationMedicTraining.CodePerformanceAnchor CodePerformanceAnchor { get; set; }
public virtual InitialTraining InitialTraining { get; set; }
public virtual GradingSystem GradingSystem { get; set; }
}
Ecco il mio GroupBy
in C #.
// get list of initial training record ids for statistics
var lstInitialTrainings = db.InitialTrainings.Where(x => x.TfoId == medicId && x.Active).Select(x => x.Id).ToList();
// get list of initial training performance anchors associated with initial training records
var lstPerformanceAnchors = db.InitialTrainingAssociations
.Where(x => lstInitialTrainings.Contains(x.InitialTrainingId)).GroupBy(t => t.PerformanceAnchorId)
.Select(s => new MedicStatistic()
{
PerformanceAnchorName = db.CodePerformanceAnchor.FirstOrDefault(v => v.Id == s.Key).PerformanceAnchor,
AnchorCount = s.Count()
}).ToList();
Il mio obiettivo
Ovviamente dal mio codice voglio raggruppare in base all'ancoraggio delle prestazioni nella tabella delle associazioni, ma ho bisogno di ulteriori informazioni dalla tabella di Initial Training
da includere nel mio ViewModel MedicStatistic
, ma ho difficoltà a trovare il modo migliore per farlo.
Il mio obiettivo generale è quello di essere in grado di ottenere il momento più recente in cui è stata completata un'ancora prestazionale dalla tabella Initial Training
.
Visivo
Tabella di addestramento iniziale (non tutti i campi sono stati acquisiti nello snippet b / c non sono importanti ai fini di questa domanda)
Tabella delle associazioni di addestramento iniziale
Quello che mi aspetto
Quindi, dalle immagini fornite sopra, come puoi vedere, ci sono più 1
per ID di ancoraggio delle prestazioni nella tabella delle associazioni , ma ognuno di essi ha InitialTrainingId
diverso. Quindi, questa specifica performance anchor è stata eseguita più volte, ma devo ottenere la data più recente dalla tabella di Initial Training
. Inoltre, devo ottenere il voto corrispondente con l'ancora dalla tabella Grading System
, in base alla data più recente.
Quindi, per l'ancoraggio delle prestazioni che è uguale a 1
... Vorrei il grado che corrisponde a InitialTrainingId
di 17
perché quel record è stato il momento più recente in cui è stato eseguito l'ancoraggio delle prestazioni di 1
.
Se avete domande per favore fatemelo sapere.
In Select
è possibile ordinare il risultato del gruppo per ottenere il InitialTraining
associato più recente di DateTakenInitial
e da lì ottenere i dati desiderati
//...omitted for brevity
.GroupBy(t => t.PerformanceAnchorId)
.Select(g => {
var mostRecent = g.OrderByDescending(_ => _.InitialTraining.DateTakenInitial).First();
// get the corresponding grade with the anchor from the Grading System table
var gradeid = mostRecent.GradingSystemId;
var gradingSystem = mostRecent.GradingSystem;
//get the most recent date from the Initial Training
var mostRecentDate = mostRecent.InitialTraining.DateTakenInitial
//..get the desired values and assign to view model
var model = new MedicStatistic {
//Already have access to CodePerformanceAnchor
PerformanceAnchorName = mostRecent.CodePerformanceAnchor.PerformanceAnchor
AnchorCount = g.Count(),
MostRecentlyCompleted = mostRecentDate,
};
return model;
});
Volete i dati raggruppati per CodePerformanceAnchor
, quindi il modo più naturale per avviare la query è nel suo DbSet
che elimina immediatamente la necessità di raggruppare:
from pa in db.CodePerformanceAnchors
let mostRecentInitialTraining
= pa.InitialTrainingAssociations
.Select(ita => ita.InitialTraining)
.OrderByDescending(tr => tr.DateTakenInitial)
.FirstOrDefault()
select new
{
pa.PerformanceAnchor,
mostRecentInitialTraining.DateTakenInitial,
mostRecentInitialTraining. ...
...
AnchorCount = pa.InitialTrainingAssociations.Count()
}
Come vedi, vengono utilizzate solo le proprietà di navigazione e la query nel suo insieme è piuttosto semplice. Presumo che la classe PerformanceAchor
abbia anche una raccolta InitialTrainingAssociations
.
Non posso garantire che EF sarà in grado di eseguirlo interamente sul lato server, tuttavia è sempre difficile con query LINQ più complesse.