Ho il seguente modello:
public Class Category{
public int Id {get;set;}
public string Name {get;set;}
public ICollection<SubCategory> SubCategories {get;set;}
}
public Class SubCategory{
public int Id {get;set;}
public string Name {get;set;}
public int CategoryId { get; set; }
public virtual Category Category{ get; set; }
public ICollection<Ticket> Tickets { get; set; }
}
public class Ticket {
public Ticket();
public int Id { get; set; }
public virtual SubCategory SubCategory{ get; set; }
public int SubCategoryId{ get; set; }
}
Voglio ottenere il gruppo di dati per Categoria e ottenere il conteggio dei ticket in ogni sottocategoria usando questa query:
Entities
.Include(h => h.SubCategories )
.ThenInclude(s => s.Tickets)
.GroupBy(s => s.Id)
.Select(t => new Cata {
Name = t.FirstOrDefault().Name,
Children = GetChildern(t.FirstOrDefault().SubCategories )
});
public List<SubCat> GetChildern(IEnumerable<SubCategories> subs)
{
var output = new List<SubCat>();
foreach (var sub in subs) {
var subcat = new SubCat();
subcat.Name = sub.Name;
if (sub.Tickets != null) {
subcat.Size = sub.Tickets.Count;
}
output.Add(subcat);
}
return output;
}
Con la Query sopra il ticket è sempre zero per tutti, ma i ticket esistono.
Non vedo perché è necessario creare un gruppo se si avvia la query in Categorie
var result= Entities
.Include(h => h.TicketSubCategories)
.ThenInclude(s => s.Tickets)
.Select(t => new Cata {
Name = t.Name,
Children= t.TicketSubCategories
.Select(ts=>new SubCat{
Name=ts.Name,
Count=ts.Tickets.Count()})
};
Concordato con @Ivan riguardo a come ha commentato sopra, qui non è necessario utilizzare un metodo personalizzato, utilizzandolo si costringerà la proiezione della query da eseguire sul lato client e non sul server (il proprio DB)
Quindi ogni categoria ha zero o più sottocategorie, e ogni sottocategoria ha zero o più biglietti. Ogni Ticket appartiene esattamente a una Sottocategoria e ogni Sottocategoria appartiene a una sola Categoria
E vuoi una query, che si traduce in gruppi di sottocategorie che hanno la stessa categoria. Volete alcune (o tutte) proprietà di ogni sottocategoria, ma soprattutto, volete il numero di ticket di ciascuna sottocategoria.
Tutti gli elementi di ogni gruppo di sottocategorie appartengono alla stessa categoria. Vuoi anche alcune (se non tutte) proprietà di questa categoria.
La soluzione è raggruppare tutte le sottocategorie in gruppi della stessa categoria (per l'uso efficiente di CategoryId). Quindi utilizzare una selezione per ottenere le proprietà desiderate.
var result = SubCategories
// group them into groups with same CategoryId
.GroupBy(subCategory => subCategory.CategoryId
// from every group take the properties you want:
.Select(group => new
{
// All SubCategories in one group belong to the same Category.
// For efficiency, take only the Category properties you plan to use,
CommonCategory = group.Key.Select(category => new
{
// take the category properties you want to use
}
// The group has a lot of SubCategories.
// For each subcategory select only the properties you want to use
SubCategories = group.Select(subCategory => new
{
// one of the properties you want is the number of Tickets of this SubCategory:
TicketCount = subCategory.Tickets.Count(),
// for efficiency: select only SubCategory properties you plan to use:
Property1 = subCategory.Property1,
Property2 = subCategory.Property2,
...
}),
});
Quindi il risultato è una sequenza di oggetti. Ogni oggetto ha due proprietà:
Le sottocategorie sono una sequenza. Ogni elemento della sequenza è un oggetto con diverse proprietà:
Da questo è facile costruire il codice in GetChildren