我正在Metait.com上学习“分层数据”课程。例如,采用一个递归实体,它可以具有到父实体及其子实体的链接: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
按如下方式初始化几个:
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();
}
那么,例如,Menuitem
对于标题,File
将会有MenuItem
带有标题Open
和的子项Save
:
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}");
}
}
}
File
---Open
---Save
但是该字段是如何初始化的Children
呢?我们没有在任何地方显式设置它的值,并且在生成的 SQL 查询中完全不存在这样的字段:
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)
);