使用EF Core操作层次结构数据

前言

以前我们存储层次结构常用Id+ParentId的方式,例如:

IdParentIdName
1null总公司
21分公司1
31分公司2
42部门A
54小组X
64小组Y

这种方式查询效率不高,比如查询分公司1下的所有小组,必须使用递归。

针对这个问题,如果你是使用Sql Server,可以尝试一下HierarchyId。

HierarchyId

HierarchyId是一种长度可变的Sql Server数据类型,它能存储带有层次结构的数据。

HierarchyId数据类型的值可以直接表示树层次结构中的位置,例如:

IdName
/总公司
/1/分公司1
/2/分公司2
/1/1/部门A
/1/1/1/小组X
/1/1/2/小组Y

HierarchyId可以使用下列函数:

  • GetAncestor :取得第n个祖先

  • GetDescendant :取得第n个子节点

  • GetLevel :取得级别

  • GetRoot :取得根

  • Parse :将字符串转换为HierarchyId

  • ToString :将HierarchyId转换为字符串,与parse正好相反

比如,查询分公司1下的所有小组,可以使用下列语句:

select * from t where [Id].GetLevel() = 3 AND [Id].GetAncestor(2) = '/1/'

HierarchyId数据类型详情请参看官方文档:https://docs.microsoft.com/zh-cn/sql/relational-databases/hierarchical-data-sql-server?view=sql-server-ver15

代码示例

下面,我们通过一个示例,演示如何使用Entity Framework Core操作HierarchyId数据类型。

建表

执行下列Sql,在数据库中建表:

create table Organizations(Id hierarchyid primary key,Name nvarchar(50)
); 

创建项目

创建控制台应用程序,然后引用nuget包EntityFrameworkCore.SqlServer.HierarchyId

定义数据模型

新建Organization.cs,代码如下:

public class Organization
{public HierarchyId Id  { get; set; }public string Name { get; set; }
}

注意,Id的类型是HierarchyId。

新建DemoContext.cs,代码如下:

public class DemoContext : DbContext
{public DbSet<Organization> Organizations { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){string connectionString = "...";optionsBuilder.UseSqlServer(connectionString, config => config.UseHierarchyId());}
}

使用config.UseHierarchyId()开启HierarchyId映射。

增删改查

现在,我们可以对HierarchyId数据类型进行操作了。

代码如下:

//增
using (var db = new DemoContext())
{db.Organizations.AddRange(new Organization { Id= HierarchyId.Parse("/"), Name= "总公司" },new Organization { Id = HierarchyId.Parse("/1/"), Name = "分公司1" },new Organization { Id = HierarchyId.Parse("/2/"), Name = "分公司2" }, new Organization { Id = HierarchyId.Parse("/1/1/"), Name = "部门A" }, new Organization { Id = HierarchyId.Parse("/1/1/1/"), Name = "小组X" }, new Organization { Id = HierarchyId.Parse("/1/1/2/"), Name = "小组Y" });db.SaveChanges();
}//删除分公司2
using (var db = new DemoContext())
{db.Organizations.Remove(db.Organizations.Where(p => p.Id == HierarchyId.Parse("/2/")).First());db.SaveChanges();
}//修改小组名称
using (var db = new DemoContext())
{var team = db.Organizations.Where(p => p.Id == HierarchyId.Parse("/1/1/1/")).First();team.Name = "Team1";team = db.Organizations.Where(p => p.Id == HierarchyId.Parse("/1/1/2/")).First();team.Name = "Team2";db.SaveChanges();
}//查询分公司1下的所有小组
using (var db = new DemoContext())
{var organizations=  db.Organizations.Where(p => p.Id.GetLevel()==3 && p.Id.GetAncestor(2)== HierarchyId.Parse("/1/")).OrderBy(p=>p.Id).ToList();foreach (var organization in organizations){Console.WriteLine(@$"{organization.Id} {organization.Name}");}
}

运行成功:

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sql2005数据导入出错问题

最近在把一个大的文本文件中的数据导入到sql2005中时&#xff0c;出现错误。<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />相同文件导入sql2000则不会出现错误。网络上一查&#xff0c;也有部分人碰到这个问题。解决的办法200…

仿UC菜单的实现

http://blog.csdn.net/hellogv/archive/2011/01/28/6168439.aspx &#xff08;另&#xff09;http://www.cnblogs.com/lichien/archive/2010/09/07/1820453.html 先来看看本文程序运行的效果&#xff1a; TabMenu 本身就是一个PopupWindow&#xff0c;PopupWindow上面放了两个G…

java将字符串转成json_Java 字符串(String)格式转json格式

json是前后端传输数据的一种文本格式&#xff0c;json其实就是字符串&#xff0c;因为前后端传输数据时&#xff0c;只能传输字符串&#xff0c;我们又想传一些对象或者列表信息&#xff0c;这都是很常见的应用场景。所以&#xff0c;我们需要在java代码中&#xff0c;把java中…

选了combobox里的选项后没激发change事件_stata 事件分析法

前言&#xff1a;因为一些原因&#xff0c;国庆节期间学的。学习过程很酸爽&#xff0c;自己并没有很多统计学及其相关软件的经验&#xff0c;网上相关资料也不是很多。我在微信公众号、知网、经管之家、B站、百度文库等很多平台找了各式的资料来学&#xff08;花了70大洋去买代…

RHCE 学习笔记(24) - LVM 逻辑卷

这一节学习了如何创建LVM&#xff0c;LVM的快照以及RAID的相关配置。对于普通的分区&#xff0c;扩展度不高&#xff0c;一旦分区格式化完成&#xff0c;很难灵活的再增加或者减少分区大小。为了解决这个问题&#xff0c;可以使用LVM&#xff08;逻辑卷&#xff09;。基本过程是…

13个圆可以画什么?数学与艺术完美邂逅!原来数学也可以这么美

全世界只有3.14 % 的人关注了爆炸吧知识你知道吗&#xff1f;Twitter logo 原来是13个圆画出来的&#xff0c;果然设计师们都是牛逼的存在&#xff01;受到 Twitter logo 设计方式的启发&#xff0c;加拿大艺术家多洛塔潘科夫斯卡决定尝试挑战自我&#xff1a;利用同样的方式&a…

什么时候使用路由再分配?

什么时候使用路由再分配?<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />路由再分配通常在那些负责从一个自治系统学习路由&#xff0c;然后向另一个自治系统广播的路由器上进行配置。如果你在使用I G R P或E I G R P&#xff…

温故知新,.Net Core遇见WinForms客户端窗体框架,在DotNet Core大一统基础上老树发芽...

什么是WinFormhttps://docs.microsoft.com/zh-cn/dotnet/desktop/winformsWindows窗体(Windows Form)&#xff0c;简称WinForms&#xff0c;是一个可创建适用于Windows的丰富桌面客户端应用的UI框架。Windows窗体开发平台支持广泛的应用开发功能&#xff0c;包括控件、图形、数…

Oracle session连接数和inactive的问题记录【转】

从上周起&#xff0c;服务器Oracle数据库出现问题&#xff0c;用不到半天&#xff0c;就会报maxsession&#xff08;150&#xff09;的问题&#xff0c;肯定是数据库的会话超过最大数了。 由于服务器跑的是文件传输应用&#xff0c;占用的请求和会话肯定很大&#xff0c;因此…

a 寻路算法 java_A*(也叫A star, A星)寻路算法Java版 | 学步园

寻路首先要理解什么是A*寻路算法&#xff0c;可以参考这三篇文章&#xff1a;下面为测试地图&#xff0c;0表示可以通行&#xff0c;1表示障碍物&#xff1a;要从点(5, 1)到点(5, 5)&#xff0c;通过A*寻路算法找到以路径为所示&#xff1a;在代码中可以修改障碍物&#xff0c;…

python多线程队列处理_Python线程和队列使用的一点思考

Python线程和队列使用的一点思考1. 斗哥采访环节请问为什么要使用线程&#xff1f;答&#xff1a;为了提高程序速度&#xff0c;代码效率呀。请问为什么要使用队列&#xff1f;答&#xff1a;个人认为队列可以保证线程安全&#xff0c;实现线程间的同步&#xff0c;比较稳。线程…

安装debian的zabbix-agent客户端

1. 下载软件源wget http://repo.zabbix.com/zabbix/2.2/debian/pool/main/z/zabbix-release/zabbix-release_2.2-1wheezy_all.deb2. 安装软件源dpkg -i zabbix-release_2.2-1wheezy_all.deb3. 更新软件源apt-get update4. 安装zabbix-agentapt-get install zabbix-agent其实deb…

看到喜欢的人时的心跳​

1 第一次和女孩子约会的猫咪.......好羞涩啊2 我要吃蛋糕&#xff01;不给买我就不走了~3 感觉自己活得都没小螃蟹精致4 完美的过程5 漫画真人6 哈哈哈哈哈哈真实合理慌的一批7 人最大的烦恼就是记性太好&#xff01;你点的每个赞&#xff0c;我都认真当成了喜欢

[Buzz.Today]2011.06.26

>> Microsoft推出Kinect for Windows SDK Kinect这玩意不得了&#xff0c;号称刚出世时比iPad和iPhone还卖得好。和当年iPhone一样&#xff0c;这玩意颇受一堆Hacker的青睐&#xff0c;做出了很多很炫的东西。 Piaoger当年曾经做过VR&#xff0c;虽然没搞出什么名堂&…

ARM公版架构迭代迅速 国产ARM架构落伍

近年来&#xff0c;ARM CPU性能可谓是突飞猛进&#xff0c;根据ARM官方消息&#xff0c;Cortex A78 CPU最高性能比5年前推出的Cortex A73 CPU提升2.5倍。ARM下一代的Matterhorn架构及Makalu架构会相对于X1/A78这一代保持30%以上的IPC性能提升&#xff0c;如果ARM的PPT不注水&am…

python 字符编码处理_浅析Python 字符编码与文件处理

Python字符编码目前计算机内存的字符编码都是Unicode&#xff0c;目前国内的windows操作系统采用的是gbk。python2默认的字符编码方式是ASCIIpython3默认的字符编码方式是Unicode.py文件头部的#coding:utf-8是帮助python识别.py文件的编码方式&#xff0c;故在写.py文件时要注意…

java 匿名初始化_关于java匿名内部类初始化法

最近无意间发现一种对象的初始化方法&#xff1a;匿名内部类初始化法List list new ArrayList(){{add("爱飘de小子");add("flyingkid");}};Map map new HashMap(){{put("name","爱飘de小子");put("age",24);}};还有这种操…

感谢生活的磨砺

感谢伤害你的人&#xff0c;因为他磨炼了你的心志&#xff01;  感谢绊倒你的人&#xff0c;因为他强化了你的双腿&#xff01;  感谢欺骗你的人&#xff0c;因为他增进了你的智慧&#xff01;  感谢藐视你的人&#xff0c;因为他觉醒了你的自尊&#xff01;  感谢遗弃…

MemoryCache 使用不当导致的一个 BUG

MemoryCache 使用不当导致的一个 BUGIntro前几天发现代码里的一个 BUG&#xff0c;原因是 MemoryCache 使用不当&#xff0c;可以对于很多人来说可能都知道&#xff0c;但还是想分享记录一下&#xff0c;避免以后写出同样的 BUGSample直接来看下面的示例吧await using var serv…

Llinux 磁盘配额的搭建和常规问题解答

1 磁盘配额的使用限制仅针对整个分区&#xff1a;磁盘配额实际运行时&#xff0c;是针对“整个分区”进行限制的&#xff0c;例如&#xff0c;如果/dev/hda5载入在/home下&#xff0c;那么&#xff0c;在/home下面的所有目 录都会受到限制。只对一般身份用户有效&#xff1a;并…