博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EF基础知识小记六(使用Code First建模自引用关系,常用于系统菜单、文件目录等有层级之分的实体)...
阅读量:6027 次
发布时间:2019-06-20

本文共 2794 字,大约阅读时间需要 9 分钟。

日常开发中,经常会碰到一些自引用的实体,比如系统菜单、目录实体,这类实体往往自己引用自己,所以我们必须学会使用Code First来建立这一类的模型.

以下是自引用表的数据库关系图:

ok,下面开始介绍从零创建一个Code First版的自引用模型.

1、往目标项目中添加EF包,通过NuGet程序包添加

 

导入相关的程序集.

2、创建自引用实体类

public class Category    {        [Key]        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]        public int CategoryId { get; private set; }        public string Name { get; set; }        public int? ParentCategoryId { get; private set; }        [ForeignKey("ParentCategoryId")]        public virtual Category ParentCategory { get; set; }         public virtual List
Subcategories { get; set; } public Category() { Subcategories = new List
(); } }

3、创建一个数据库上下文,该上下文必须继承DbContext,代码如下:

public class EF6RecipesContext : DbContext    {        public DbSet
Categories { get; set; } public EF6RecipesContext() : base("name=EF6RecipeEntities") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity
().HasMany(cat => cat.Subcategories).WithOptional(cat => cat.ParentCategory); } }

4、截至这一步,分析下代码,典型的目录实体,从实体类可以看出该实体拥有单个父类型、子类型集合,这里比较特殊的是,这里的父类型和子类型都是自己,也就是自引用.注意:一个没有付类型的实体,该实体就是整个继承类型的最顶端.

5、编写测试代码:

static void Main(string[] args)        {            Example();        }        static void Example()        {            using (var context = new EF6RecipesContext())            {                var first = new Category { Name = "第一级菜单" };                var second = new Category { Name = "第二级菜单" };                first.Subcategories.Add(second);                second = new Category { Name = "第二级菜单" };                first.Subcategories.Add(second);                second = new Category { Name = "第二级菜单" };                first.Subcategories.Add(second);                var top = new Category { Name = "顶级菜单" };                top.Subcategories.Add(first);                context.Categories.Add(top);                context.SaveChanges();            }            using (var context = new EF6RecipesContext())            {                var roots = context.Categories.Where(c => c.ParentCategory == null);                roots.ToList().ForEach(root => Print(root, 0));            }            Console.ReadKey();        }        static void Print(Category cat, int level)        {            StringBuilder sb = new StringBuilder();            Console.WriteLine("{0}{1}", sb.Append(' ', level).ToString(), cat.Name);            cat.Subcategories.ForEach(child => Print(child, level + 1));//递归,直到最后遍历的节点没有子节点集合,则跳出递归循环        }

 

简单解释下测试代码的逻辑:

(1)、从所有的节点中获取没有父节点的节点,该节点为顶级节点

(2)、然后通过递归将该顶级节点下面的所有的子节点全部遍历出来,每当递归到的节点含有子节点集合,则递归的深度加1.当一个继承链遍历完毕,继续遍历第二个继承链.

 

转载地址:http://inzhx.baihongyu.com/

你可能感兴趣的文章
Bogo排序
查看>>
帮助自定义选择框样式的Javascript - DropKick.js
查看>>
android学习——popupWindow 在指定位置上的显示
查看>>
把Android源代码加入SDK
查看>>
深踩 AndroidStudio 缓存的坑
查看>>
RandomAccessFile和memory-mapped files
查看>>
.NET Core采用的全新配置系统[3]: “Options模式”下的配置是如何绑定为Options对象...
查看>>
MySQL隔离级别
查看>>
URAL 1051 Simple Game on a Grid
查看>>
求时间差的sql语句。 比如如下数据
查看>>
PHP后期静态绑定分析与应用
查看>>
001 有关中文乱码的处理
查看>>
[转载]大型网站运维探讨和心得
查看>>
NIO学习系列:核心概念及基本读写
查看>>
vc中ASSERT()和VERIFY()区别
查看>>
centOS 搭建SVN服务器,提交自动发布代码,详细教程,及注意事项
查看>>
HTML<div><span>字符实体
查看>>
CentOS6.3安装PowerVault MD Storage Manager
查看>>
HTML 表格
查看>>
VMware 虚拟化编程(7) — VixDiskLib 虚拟磁盘库详解之三
查看>>