C# GroupBy Trouble

c# entity-framework-core

Question

As of now, I am trying to create a list that groups based on certain criteria and then display that list in the view.

I have two database tables and one is an association table.

First Table

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; }
}

Second Table (Association Table)

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; }
}

Here is my 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();

My Goal

Obviously from my code I want to group by the performance anchor in the association table, but I need more information from the Initial Training table to include in my ViewModel MedicStatistic, but I am having trouble figuring out the best way to do it.

My overall goal is to be able to get the most recent time a performance anchor was completed from the Initial Training table.

Visual

Initial Training Table (not all fields were captured in snippet b/c they're not important for the purpose of this question)

enter image description here

Initial Training Association Table

enter image description here


What I expect

So, from the pictures provided above as you can see there are multiple 1's for performance anchor id's in the association table, but they each have different InitialTrainingId. So, this specific performance anchor has been done multiple times, but I need to get the most recent date from the Initial Training table. Also, I need to get the corresponding grade with the anchor from the Grading System table, based on the most recent date.

So, for the performance anchor that equals 1.. I would want the grade that corresponds to the InitialTrainingId of 17 because that record was the most recent time that the performance anchor of 1 was done.

If you have any questions please let me know.

1
0
6/6/2019 5:54:10 PM

Accepted Answer

In the Select you can order the group result to get the most recent associated InitialTraining by DateTakenInitial, and from there get the desired data

//...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;
});
0
6/6/2019 5:46:28 PM

Popular Answer

You want the data grouped by CodePerformanceAnchor, so the most natural way to start the query is at its DbSet which immediately eliminates the necessity of grouping:

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()
}

As you see, only navigation properties are used and the query as a whole is pretty straightforward. I assume that the PerformanceAchor class also has an InitialTrainingAssociations collection.

I can't guarantee that EF will be able to execute it entirely server-side though, that's always tricky with more complex LINQ queries.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow