Rafy 领域实体框架 - 树型实体功能(自关联表)
在 Rafy 领域实体框架中,对自关联的实体结构做了特殊的处理,下面对这一功能进行讲解。
场景
在开发数据库应用程序时,往往会遇到自关联表的场景。例如,分类信息、组织架构中的部门、文件夹信息等,都是不限制层级的。如下图中操作系统的文件夹:
在开发这类程序时,往往是设计一张表,表中的一个可空的外键直接引用这张表本身。对应的实体如下图:
而针对这样的场景,许多ORM框架都不做默认的处理,开发者往往每次都要做重复的工作:建立类似结构的表,编写关系处理代码,编写查询代码……而这种场景经常会出现,所以 Rafy 实体框架中,默认就支持了树型实体的一系列功能,来降低重复劳动。
功能及使用说明
在 Rafy 中的树型实体功能,只需开发者使用一行代码为指定的实体打开这个功能,框架会自动完成以下工作:
- 自动添加实体的自引用关系。自动生成数据库自关联表。
- 自动维护树节点的 TreeIndex 索引。
- 自带多个查询,用于查询树节点。
- 查询结果自动转变为树的结构。
- 支持树节点的按需加载。
下面,将逐一进行讲解。
打开树型实体功能
开发者只需使用一行代码即可让指定的实体转变为树型实体。在指定实体的配置代码中,添加下面这行代码即可:
自动添加实体的自引用关系
实体基类上已经默认带有以下几个属性,来表达树节点之间的关系。
当某个实体类型被配置为树型实体时,这几个属性才会有意义。
SupportTree:指示该实体是否为树型实体。
TreeIndex:树节点的编码、索引。此属性会映射为数据库中的字段。
TreePId:该树节点的父节点的 Id。此属性会映射为数据库中的字段。
TreeParent:该树节点的父节点实体。
TreeChildren:该树节点的所有子节点集合。
自动生成数据库自关联表
运行程序后,该实体对应的表将会自动添加两个字段:TreeIndex、TreePId,如下图:
自动维护树节点的 TreeIndex 索引
TreeIndex 是树结点的系统编号,由框架自动维护。下图显示了一个正在使用的树的 TreeIndex 的格式:
这个属性不但可以用于显示,更重要的是它是树型实体大量功能的结构基础。例如,当查询某个节点下的所有节点时,就是通过 TreeIndex 来进行模糊匹配的。所以这个属性的值非常重要,只能由框架来自行维护,而不能由开发者来设置。
开发者可以通过 TreeParent、TreeChildren、TreePId 等属性来变更节点与节点之间的父子关系,这时,对应的节点的 TreeIndex 则会同时自动变更。
树结构的表示
树的结构非常重要,我手画了张草图来表示:
主要由三个类型构成整个树:EntityList、Entity、EntityTreeChildren。这个结构可以表示完整的一棵树,也可以表示部分树。其中,EntityList 用于存储树的根节点(如果是部分树,则表示最上层节点);Entity 表示树中的每一个节点;EntityTreeChildren 集合则表示某个节点下的子节点。
另外,EntityTreeChildren 集合可以按需加载。当它还没有进行加载时,遍历整个树只能遍历到当前已经在内存中的树节点。例如,上图中,Root3的子节点没有被加载,1.2.2 的子节点也没有被加载。
那么,如何加载还没有加载到内存中的节点呢?这需要使用到 ITreeComponent 接口中的 LoadAllNodes 方法。EntityList、Entity、EntityTreeChildren 这三个类型都实现了 ITreeComponent 接口,下面是这个接口的定义:
另外,可以使用其中的 EachNode 方法来以深度优先的算法遍历整棵树。
自带多个查询,用于查询树节点
实体仓库中带有许多查询方法,其中一些是专门为树型实体设计的:
- GetTreeRoots:查询所有的根节点。
- GetByTreePId:查找指定树节点的直接子节点。
- GetByTreeParentIndex:递归查找指定父索引号的节点下的所有子节点。
- LoadAllTreeParents:递归加载某个节点的所有父节点。使用此方法后,指定节点的父节点将被赋值到它的 TreeParent 属性上。
- GetAllTreeParents:获取指定索引对应的树节点的所有父节点。 查询出的父节点同样以一个部分树的形式返回。
另外,一些非树实体的查询方法,对于树型实体也是可用的。如 GetAll、GetByParentId 等。但是也会有所区别,例如 GetAll 方法在查询非树实体时,查询出的实体列表中包含所有的实体;但是在查询树型实体时,结果会按照树的结构来进行加载,即列表中只会有根节点,其它节点则分别在根节点的下级节点中。
同时,这些查询往往支持是否使用贪婪加载的参数。以 GetTreeRoots 方法举例,它的接口是这样的:public EntityList GetTreeRoots(EagerLoadOptions eagerLoad = null); 。它在默认情况下只返回根节点,而根节点中的子节点是没有被加载的。但是,我们可以通过参数中的 eagerLoad 来指定,在加载根节点的同时,把所有的子节点都加载上。
以上只是对一些接口做一些必要的解释,具体的使用方法及其它的接口,请参照注释及源码中的单元测试。
限制
说了上面这么多自带的功能,但是 Rafy 中树型实体的设计也有这的限制:一个树型实体类型对应的数据表中,只能存储一棵树。树中的所有节点的 TreeIndex 都必须是唯一的。
好了,鉴于篇幅,这篇文章只是简单地讲解了树型实体中的重点概念及功能,并没有深入说明。这是因为,在使用的过程中你会发现,一般情况下用起来非常容易,只需要打开树型实体功能,并调用想要的查询就可以了,用不到特别复杂的 API。如果确实需要深入了解,那么在理解了整个树的结构设计后,再结合帮助、注释以及源码中的单元测试,相信也会比较简单。
Rafy 领域实体框架 - 树型实体功能(自关联表)的更多相关文章
- Rafy 领域实体框架演示(2) - 新功能展示
本文的演示需要先完成上一篇文章中的演示:<Rafy 领域实体框架示例(1) - 转换传统三层应用程序>.在完成改造传统的三层系统之后,本文将讲解使用 Rafy 实体框架后带来的一些常用功能 ...
- Rafy 领域实体框架演示(4) - 使用本地文件型数据库 SQLCE 绿色部署
本系列演示如何使用 Rafy 领域实体框架快速转换一个传统的三层应用程序,并展示转换完成后,Rafy 带来的新功能. <福利到!Rafy(原OEA)领域实体框架 2.22.2067 发布!> ...
- 福利到!Rafy(原OEA)领域实体框架 2.22.2067 发布!
距离“上次框架完整发布”已经过去了一年半了,应群中的朋友要求,决定在国庆放假之际,把最新的框架发布出来,并把帮助文档整理出来,这样可以方便大家快速上手. 发布内容 注意,本次发布,只包含 Rafy ...
- Rafy 领域实体框架简介
按照最新的功能,更新了最新版的<Rafy 领域实体框架的介绍>,内容如下: 本文包含以下章节: 简介 特点 优势 简介 Rafy 领域实体框架是一个轻量级 ORM 框架. 与一般的 ORM ...
- Rafy 领域实体框架演示(3) - 快速使用 C/S 架构部署
本系列演示如何使用 Rafy 领域实体框架快速转换一个传统的三层应用程序,并展示转换完成后,Rafy 带来的新功能. <福利到!Rafy(原OEA)领域实体框架 2.22.2067 发布!> ...
- 领域实体框架Rafy2 发布了
在2009年我在codeplex发布了1.0版本OpenExpressApp,下载地址:http://openexpressapp.codeplex.com/.OEA 1.0 作为我十多年开发工作的一 ...
- 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述
微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...
- Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结
在前阵子,我对实体框架进行了一定的研究,然后把整个学习的过程开了一个系列,以逐步深入的方式解读实体框架的相关技术,期间每每碰到一些新的问题需要潜入研究.本文继续前面的主题介绍,着重从整体性的来总结一下 ...
- C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# 6 ...
随机推荐
- Expert 诊断优化系列------------------锁是个大角色
前面几篇已经陆续从服务器的几个大块讲述了SQL SERVER数据库的诊断和调优方式.加上本篇可以说已经可以完成常规的问题诊断及优化,本篇就是SQL SERVER中的锁.为了方便阅读给出系列文章的导读链 ...
- [翻译]理解Swift中的Optional
原文出处:Understanding Optionals in Swift 苹果新的Swift编程语言带来了一些新的技巧,能使软件开发比以往更方便.更安全.然而,一个很有力的特性Optional,在你 ...
- WPF +MVVM(Caliburn.Micro)项目框架
最近做了一个软件,这个软件不是网站,但是与HTML,AJAX等技术密切相关,也不是只有单纯的数据库增删改查,还涉及到线程协调,比较复杂的文本处理…… 这样的软件,用OA,ERP的框架显然是不合适的,因 ...
- sublime text2 安装less2css插件
之前一直用PhpStorm,功能十分强大,各种插件也有,不过比较占内存,有时候,左边的项目列表都刷不出来,今天又出现了这个问题,于是果断换sublime了. 由于项目中要用less编译,所以得装个le ...
- 一次Mysql 死锁事故
故障描述: 简单描述一下需求:我们写的一个计步器的客户端软件,用户通过手机客户端将用户的运动计步信息传到服务器. 服务器侧记录每个用户每次上传明细,同时每个用户有一个汇总值,参与全省排名. 1.加入明 ...
- Module-Zero之租户管理
返回<Module Zero学习目录> 开启多租户 租户实体 租户管理者 默认租户 开启多租户 ABP和Module-Zero可以运行多租户或单租户模式.多租户默认是禁用的.我们可以在mo ...
- 学习SpringMVC——从HelloWorld开始
前言: 时隔十二年,中国女排最终过关斩将,用3:1的成绩证明了自己的实力,霸气夺冠,为中国赢得了一枚意义非常的金牌.这是一次全民的狂欢,一场视听盛宴,带给我们不仅是熠熠生辉的金牌,更传递出的是一种女排 ...
- SSIS Execute SQL Task 用法
Execute Sql Task组件是一个非常有用的Control Flow Task,可以直接执行SQL语句,例如,可以执行数据更新命令(update,delete,insert),也可以执行sel ...
- SQL Server中的窗口函数
简介 SQL Server 2012之后对窗口函数进行了极大的加强,但对于很多开发人员来说,对窗口函数却不甚了解,导致了这样强大的功能被浪费,因此本篇文章主要谈一谈SQL Server中窗口函 ...
- Dnsmasq安装与配置
默认的情况下,我们平时上网用的本地DNS服务器都是使用电信或者联通的,但是这样也导致了不少的问题,首当其冲的就是上网时经常莫名地弹出广告,或者莫名的流量被消耗掉导致网速变慢.其次是部分网站域名不能正常 ...