Sto usando EF 7.0.0.0-rc1-final.
Ho una struttura ad albero con relazioni uno-a-molti da GrandGrandParent a GrandParent a Da padre a figlio:
public class GrandGrandParent
{
public int ID { get; set; }
public string Name { get; set; }
public virtual List<GrandParent> GrandParents { get; set; }
public GrandGrandParent()
{
this.GrandParents = new List<GrandParent>();
}
}
public class GrandParent
{
public int ID { get; set; }
public string Name { get; set; }
public virtual GrandGrandParent GrandGrandParent { get; set; }
public virtual List<Parent> Parents { get; set; }
public GrandParent()
{
this.Parents = new List<Parent>();
}
}
public class Parent
{
public int ID { get; set; }
public string Name { get; set; }
public virtual GrandParent GrandParent { get; set; }
public virtual List<Child> Children { get; set; }
public Parent()
{
this.Children = new List<Child>();
}
}
public class Child
{
public int ID { get; set; }
public string Name { get; set; }
public virtual Parent Parent { get; set; }
}
Utilizzando EF Core 1.0 (EF 7), come posso creare una query LINQ (o con sottoquery) che mi fornisce l'intero albero, dato un determinato ID di un pronipote?
Posso .Include () un livello su o giù, forse sono cieco per l'ovvio? Questo mi dà il GrandGrandParent e l'elenco dei GrandParent:
var ggparent1 = from ggp in myDbContext.GrandGrandParent
.Include(ggp => ggp.GrandParents)
where ggp.ID == 2
select ggp;
Voglio ottenere l'intero albero, fino alla lista dei bambini. Devo ricorrere al codice di un ciclo foreach () e creare manualmente l'albero?
Vorrei solo andare con il modulo Linq:
private static void Test0(ApplicationDbContext myDbContext)
{
var ggparent = myDbContext.GrandGrandParents
.Include(ggp => ggp.GrandParents)
.ThenInclude(gp => gp.Parents)
.ThenInclude(p => p.Children)
.FirstOrDefault(ggp => ggp.ID == 3);
if (ggparent == null)
{
DebugPrint("GrandGrandParent not found");
return;
}
DebugPrint("GrandGrandParent:");
DebugPrint(ggparent);
if (ggparent.GrandParents == null)
{
DebugPrint("GrandParents null");
return;
}
foreach (var gparent in ggparent.GrandParents)
{
DebugPrint(gparent);
if (gparent.Parents == null) continue;
foreach (var parent in gparent.Parents)
{
DebugPrint(parent);
if (parent.Children == null) continue;
foreach (var child in parent.Children)
{
DebugPrint(child);
}
}
}
int changeCount = myDbContext.SaveChanges();
DebugPrint(string.Format("ChangeCount={0}", changeCount));
}
Quindi non devi fare le domande secondarie da soli. Ma è possibile aggiungere la registrazione per vedere le query SQL che EF crea effettivamente.
Se è necessario l'albero completo non è necessario select
. È possibile utilizzare select per estrarre una parte dell'albero dei risultati o creare un nuovo oggetto (piatto) fuori dalla gerarchia.
Un esempio in cui applico una gerarchia con solo due livelli (con molti a molti) per ottenere gli elementi per una lista di selezione raggruppata:
var result =
(from c in dbContext.EventTypes
join j in dbContext.EventType2EventTypes on c.Id equals j.ChildEventTypeId
join p in dbContext.EventTypes on j.ParentEventTypeId equals p.Id
where p.EventTypeLevel == EventTypeLevel.First && c.EventTypeLevel == EventTypeLevel.Second
orderby p.SortOrder, p.Id, c.SortOrder, c.Id
select new SelectListItem
{
Text = c.NameDe,
Value = c.Id.ToString(),
Group = GetParentEventTypeSelectListGroup(p.NameDe)
}).AsNoTracking();