Некоторые данные представляют иерархическую структуру по типу деревьев, например, меню, где один пункт меню может иметь подменю. Или файловая система, где в каталоге могут быть другие каталоги. Рассмотрим, как в Entity Framework мы можем создать и использовать подобную иерархическую структуру.
Определим следующую сущность MenuItem:
public class MenuItem { public int Id { get; set; } public string? Title { get; set; } public int? ParentId { get; set; } public MenuItem? Parent { get; set; } public List<MenuItem> Children { get; set; } = new(); }
MenuItem представляет пункт меню, который может иметь подменю. Свойство Title представляет некоторый текст пункта меню. Свойство Parent
хранит ссылку на родительский пункт меню при его наличии, а ParentId
- id родительского пункта меню. Причем поскольку у пунктов меню верхнего уровня
не может быть родительских меню, то свойства ParentId
и Parent
определены как необязательные. А свойство Children
представляет пункты подменю.
И определим следующий контекст данных:
using Microsoft.EntityFrameworkCore; public class ApplicationContext : DbContext { public DbSet<MenuItem> MenuItems { get; set; } = null!; protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=helloapp.db"); } }
В итоге при создании базы данных будет генерироваться следующая таблица:
CREATE TABLE "MenuItems" ( "Id" INTEGER NOT NULL, "Title" TEXT, "ParentId" INTEGER, CONSTRAINT "FK_MenuItems_MenuItems_ParentId" FOREIGN KEY("ParentId") REFERENCES "MenuItems"("Id"), CONSTRAINT "PK_MenuItems" PRIMARY KEY("Id" AUTOINCREMENT) );
Использование MenuItem:
using (ApplicationContext db = new ApplicationContext()) { // пересоздаем бд db.Database.EnsureDeleted(); db.Database.EnsureCreated(); // добавляем начальные данные MenuItem file = new MenuItem { Title = "File" }; MenuItem edit = new MenuItem { Title = "Edit" }; MenuItem open = new MenuItem { Title = "Open", Parent = file }; MenuItem save = new MenuItem { Title = "Save", Parent = file }; MenuItem copy = new MenuItem { Title = "Copy", Parent = edit }; MenuItem paste = new MenuItem { Title = "Paste", Parent = edit }; db.MenuItems.AddRange(file, edit, open, save, copy, paste); db.SaveChanges(); } using (ApplicationContext db = new ApplicationContext()) { // получаем все пункты меню из бд var menuItems = db.MenuItems.ToList(); Console.WriteLine("All Menu:"); foreach (MenuItem m in menuItems) { Console.WriteLine(m.Title); } Console.WriteLine(); // получаем определенный пункт меню с подменю var fileMenu = db.MenuItems.FirstOrDefault(m => m.Title == "File"); if(fileMenu != null) { Console.WriteLine(fileMenu.Title); foreach(var m in fileMenu.Children) { Console.WriteLine($"---{m.Title}"); } } }
Консольный вывод программы:
All Menu: File Edit Open Save Copy Paste File ---Open ---Save