מבנה נתונים היררכי . EF CORE
-
public class Item { public string Name { get; set; } public int? Id { get; set; } public int? Price { get; set; } public int? GroupId { get; set; } public Group Group { get; set; } public ICollection<Group> Groups { get; set; } public ICollection<Group2Item> Groups2Item { get; set; } } public class Group { [Key] public int? Id { get; set; } public string Name { get; set; } public List<Item> Items { get; set; }//parent public List<Group2Item> Group2Items{ get; set; }//parent public List<Item> ItemsChildren { get; set; }//children } public class Group2Item { [Key] public int Id { get; set; } public int ItemId { get; set; } public Item Item { get; set; } public int GroupId { get; set; } public Group Group{ get; set; } } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Item>() .HasOne<Group>(i => i.Group) .WithMany(o => o.ItemsChildren) .HasForeignKey(i=> i.GroupId); modelBuilder.Entity<Group>() .HasMany(g => g.Items) .WithMany(g=> g.Groups) .UsingEntity<Group2Item>( j => j .HasOne(pt => pt.Item) .WithMany(t => t.Groups2Item) .HasForeignKey(pt => pt.ItemId), j => j .HasOne(pt => pt.Group) .WithMany(p => p.Group2Items) .HasForeignKey(pt => pt.GroupId), j => { j.HasKey(t => new { t.GroupId, t.ItemId }); }); }
-
מבחינתי הקוד הרלוונטי הוא כזה:
public class Item { public string Name { get; set; } public int? Id { get; set; } public int? Price { get; set; } public int? GroupId { get; set; } public Group Group { get; set; } } public class Group { public int? Id { get; set; } public string Name { get; set; } public List<Item> ItemsChildren { get; set; } }
אתה לא ציינת את העיקר, מה אתה הולך לעשות עם זה. זה לדעתי מאוד משנה. בכל אופן אם אקח את דבריך כפשוטם, ואניח שהמטרה היא שליפה של אובייקט יחיד עם כל צאצאיו רק בשלוש רמות, אפשר לכתוב את כל השלושה רמות מפורש בשאילתה, ככה:
var item = db.Items.Where(i => i.Id == 12).Select(it => new { it.Name, it.Price, Group = new { it.Group.Name, Items = it.Group.ItemsChildren.Select(it2 => new { it2.Name, it2.Price, Group = new { it2.Group.Name, Items = it2.Group.ItemsChildren.Select(it3 => new { it3.Name, it3.Price }) } }) } });
זה לא נראה אלגנטי אבל זה יעבוד טוב.
אם רוצים שליטה על יותר רמות של היררכיה, אני חושב שאין מנוס מלעשות לולאה, שממלאת מחלקות מתאימות.
אם רוצים מיטוב ולעשות הכל ברמת הSQL אפשר לעשות שאילתות מורכבות שמתעסקות ברקורסיה כזאת (אני רואה על זה הרבה בגוגל sql tree structure query), ולוותר בנקודה הספציפית הזאת על הEF. -
רקורסיה על מבנה היררכי ב-SQL נעשה בד"כ על ידי Recursive CTE. אבל מחיפושי גוגל נראה שזה לא נתמך ב-EF.
אם תעשה את זה ברמת SQL תקבל רשימה שטוחה, אין עצים ב-SQL (כאשר עושים JOIN, אז EF יודע לפרסר את התשובה ולבנות ממנה עץ).
הרקורסיה שאתה יכול לעשות ב-EF זה מה ש@dovid כתב:אני חושב שאין מנוס מלעשות לולאה, שממלאת מחלקות מתאימות