So, I'm building a web app to display information about my campus's academic offerings. The site is supposed to lazy-load a list of programs based on some user-selected criteria.
The issue I'm running into is how to properly sort the data in conjunction with a complex set of associations.
At the core of the Model is a fairly simple Program class.
public abstract class Program
{
public Program()
{
ProgramDegrees = new HashSet<ProgramDegree>();
ProgramOptions = new HashSet<ProgramOption>();
Keywords = new HashSet<Keyword>();
Departments = new HashSet<Department>();
}
[Key]
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
//...some virtual navigation properties go here
}
In my Controller, I query for the programs based on some user inputs, then order and limit them.
Programs = Programs.OrderBy(p => p.Name).Skip(cardsStartIndex ?? 0).Take(15);
What's tripping me up is the ProgramOptions and how to order them alongside the programs in alphabetical order. Options are basically a sub-field or emphasis within an academic program, such as an Illustration option in the Design program.
public partial class ProgramOption : AbstractProgram
{
[Key]
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
public virtual Program Program { get; set; }
}
I map the relationship in my data context using the Fluent API
modelBuilder.Entity<Program>()
.HasMany(e => e.ProgramOptions)
.WithRequired(e => e.Program)
.WillCascadeOnDelete(false);
In the UI, we're listing ProgramOptions right alongside programs themselves. That's all well and good. Once I have the list of programs that matches any search criteria, I just add the ProgramOptions associated with each program to the View Model.
Just one teeny problem. Even though I sort the Programs found by their Name property so they display in alphabetical order, adding the ProgramOptions in after the fact means that a given option always displays alongside its program, even if the Option name should be alphabetically elsewhere in the list. This makes the list less useful if you're scanning for a particular heading. I could just manually sort the final list within the View Model, except that the UI design calls for an infinite scroll effect. So even if the first load was alphabetical, the next 15 or so entities wouldn't be.
My first thought was to use an inheritance pattern (make ProgramOptions a subclass of Programs, or of some third AbstractPrograms class), but that's proving to be far more complicated than its worth given all the other associations.
The only other solution I can think of is to select all the programs from the database, construct the relevant ViewModel for all of them and their options, and then take the number I want to include on the next load. I dislike this because it more or less defeats half the purpose of lazy loading (fetching less data from the DB at one time, and delivering it to the client piece-by-piece).
Is there a solution or pattern that I'm overlooking here?