日常开发中,经常会碰到一些自引用的实体,比如系统菜单、目录实体,这类实体往往自己引用自己,所以我们必须学会使用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<Category> Subcategories { get; set; }
public Category()
{
Subcategories = new List<Category>();
}
}

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

    public class EF6RecipesContext : DbContext
{
public DbSet<Category> Categories { get; set; }
public EF6RecipesContext()
: base("name=EF6RecipeEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Category>().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, ));
}
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)、从所有的节点中获取没有父节点的节点,该节点为顶级节点

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

EF基础知识小记六(使用Code First建模自引用关系,常用于系统菜单、文件目录等有层级之分的实体)的更多相关文章

  1. EF基础知识小记四(数据库=>模型设计器)

    EF基础知识小记三(设计器=>数据库)介绍了如何创建一个空设计器模型,并如何将模型同步到数据库的表中,本文则主要介绍如何将一个存在的数据库同步到模型设计器中.为了能快速的模拟这个过程,给出一下建 ...

  2. 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射

    使用Code First建模自引用关系笔记   原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...

  3. 《Entity Framework 6 Recipes》中文翻译系列 (6) -----第二章 实体数据建模基础之使用Code First建模自引用关系

    2-5 使用Code First建模自引用关系 问题 你的数据库中一张自引用的表,你想使用Code First 将其建模成一个包含自关联的实体. 解决方案 我们假设你有如图2-14所示的数据库关系图的 ...

  4. EF基础知识小记七(拆分实体到多个表以及拆分表到多个实体)

    一.拆分实体到多个表 1.在日常开发中,会经常碰到一些老系统,当客户提出一些新的需求,这些需求需要在原来的表的基础上加一些字段,大多数人会选择通过给原表添加字段的方式来完成这些需求,方法,虽然可行,但 ...

  5. EF基础知识小记五(一对多、多对多处理)

    本文主要讲EF一对多关系和多对多关系的建立 一.模型设计器 1.一对多关系 右键设计器新增关联 导航属性和外键属性可修改 2.多对多关系 右键设计器新增关联 模型设计完毕之后,根据右键设计器根据模型生 ...

  6. EF基础知识小记二

    1.EF的常用使用场景 (1).维护一个已经存在的数据库,VS提供了工具帮助我们把数据库中的表和视图等对象导入到实体框架.        [数据库=>模型(Database First)] (2 ...

  7. EF基础知识小记一

    1.EF等ORM解决方案出现的原因 因为软件开发中分析和解决问题的方法已经接近成熟,然后关系型数据库却没有,很多年来,数据依然是保存在表行列这样的模式里,所以,在面相对象和高度标准化的数据库中产生了一 ...

  8. EF基础知识小记三(设计器=>数据库)

    本文主要介绍通过EF的设计器来同步数据库和对应的实体类.并使用生成的实体上下文,来进行简单的增删查该操作 1.通过EF设计器创建一个简单模型 (1).右键目标项目添加新建项 (2).选择ADO.Net ...

  9. 使用Code First建模自引用关系笔记

    原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasRequired:前者(A)包含后者(B)一个不为 ...

随机推荐

  1. 在linux系统中安装VSCode(Visual Studio Code)和图标的创建方式

    本文转载自:https://www.cnblogs.com/lzpong/p/6145511.html,自己添加了一些关于依赖包安装的. 1.从官网下载压缩包(话说下载下来解压就直接可以运行了咧,都不 ...

  2. Proxy Hosted Virtual

    http://books.sonatype.com/nexus-book/reference/confignx-sect-manage-repo.html Public Repositories 对外 ...

  3. chrome添加 postman扩展程序图文简介

    Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件.无论是web前端开发 或 android.ios开发,只要涉及调用后端接口,postman这类型工具就必不可少了.相对于 ...

  4. TableView编辑状态下跳转页面的崩溃处理

    29down votefavorite 12 I have a viewController with a UITableView, the rows of which I allow to edit ...

  5. matlab练习程序(生成希尔伯特曲线)

    能够使用这样一条线遍历图像中所有的像素,不过这里没有这样做,而只是生成了这样一条曲线. 程序中h,w是最终图像的高和宽,n为希尔伯特曲线阶数. 这里如果n等于log2(h)或log2(w),则图像就全 ...

  6. Java火焰图在Netflix的实践

    转自 http://www.infoq.com/cn/news/2015/08/java-flamegraph 亲爱的读者:我们最近添加了一些个人消息定制功能,您只需选择感兴趣的技术主题,即可获取重要 ...

  7. hdu1002 A + B Problem II(高精度加法) 2016-05-19 12:00 106人阅读 评论(0) 收藏

    A + B Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  8. cordova使用webrtc与网页端及移动端视频、语音聊天

    最近在做一个移动端与移动端.网页端文字.视频.语音聊天的功能.文字聊天使用websocket,在网上很多资料,也没什么难度.但是在视频.语音聊天上遇到了小小的难点.之前一直在找一些SDK想快速开发,例 ...

  9. 哈希连接(hash join) 原理

    哈希连接(hashjoin)    访问次数:驱动表和被驱动表都只会访问0次或1次.    驱动表是否有顺序:有.    是否要排序:否.    应用场景: 1. 一个大表,一个小表的关联:     ...

  10. Eclipse C++,Cygwin 64,gcov,lcov 单体&覆盖率测试环境搭建笔记

    1.下载并安装 Eclipse IDE for C/C++ Developers https://eclipse.org/downloads/packages/eclipse-ide-cc-devel ...