使用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,一经查实,立即删除!

相关文章

仿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…

选了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…

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

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

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

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

看到喜欢的人时的心跳​

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

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

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

MemoryCache 使用不当导致的一个 BUG

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

22岁少年破解史上最严重网络攻击,拯救全球互联网,三个月后却被FBI逮捕

转自&#xff1a;大数据文摘编译&#xff1a;牛婉杨2017年&#xff0c;一位名叫Marcus Hutchins的少年从有史以来最严重的网络攻击事件“WannaCry 勒索病毒”中拯救了互联网。如果你是个geek&#xff0c;那么你对WannaCry这个名字一定不陌生&#xff0c; 这是一种可以自行传播的…

使用 Git Extensions 简单入门 Git

使用 Git Extensions 简单入门 Git—— 独立观察员 2015.11.25前言关于这个主题&#xff0c;之前我录了段视频教程&#xff0c;在本地看清晰度还可以&#xff0c;但传到优酷上就很不清晰了&#xff0c;即使是后来重制后还是一样不清晰&#xff0c;所以现在想整理成文字版。当然…

各省地图都像些什么?

全世界只有3.14 % 的人关注了爆炸吧知识人们常说中国地图的形状像一只雄鸡&#xff0c;但具体到每一个省区则并没有一个明确的说法。看看下面这一套省区地图对应的有趣的想象&#xff0c;你觉得像还是不像&#xff1f;★安徽有人说安徽像一只斜倒挂着的蝙蝠&#xff0c;你能看出…

Silverlight中摄像头的运用—part2

Silverlight 4 中摄像头的运用—part1将跟踪颜色视作输入 好了&#xff0c;我们能够跟踪到这个颜色了&#xff0c;那这么做的意义是什么呢&#xff1f;实际上&#xff0c;我们可以根据它的位置来移动东西。接下来的例子中&#xff0c;创建的一个球会跟随这个颜色一起移动。你可…

同学,解决下这个 Bug!

一些解决 Bug 的小技巧大家好&#xff0c;我是鱼皮。学编程的过程中&#xff0c;我们会遇到各式各样的 Bug&#xff0c;也常常因为它们而感到头秃。但随着你不断解决 Bug、积累经验&#xff0c;就会发现其实解决 Bug 也是有套路的。今天分享下鱼皮自己总结的解决 Bug 套路&…

如果给你一个亿,你想去干嘛?各专业的科研狗是这样回答的……

全世界只有3.14 % 的人关注了爆炸吧知识“如果现在给你一个亿&#xff0c;你想去做什么&#xff1f;”每天都被穷醒的小天一看到&#xff0c;立马展开了丰富的想象力&#xff1a;首先&#xff0c;当然少不了买买买&#xff0c;将一切之前想要的、不想要的&#xff0c;贵的、更贵…

头文件定义全局变量_5.2 C++局部变量与全局变量 | 输出局部全局变量

C局部变量C局部变量是指&#xff1a;在一个函数内部定义的变量&#xff0c;它只在本函数范围内有效&#xff0c;也就是说只有在本函数内才能使用它&#xff0c;在此函数以外是不能使用这些变量的。同样&#xff0c;在复合语句中定义的变量只在本复合语句范围内有效&#xff0c;…

java float转换成long_在Java中如何将float转换为long或int数据类型?

float f1.2f;double dDouble.parseDouble(String.valueOf(f));System.out.println(d);直接转换会设计到精度问题&#xff0c;所以需要借助字符串 保证不丢失数据www.shufadashi.com防采集。楼主您好&#xff0c;如果float是个整数&#xff0c;强制转换即可&#xff0c;可以捕捉…

Spark 1.2 发布,开源集群计算系统

2019独角兽企业重金招聘Python工程师标准>>> Spark 1.2 发布&#xff0c;此版本包括 172 位贡献者和超过 1000 个 commits。 此版本包括 Spark 核心操作和性能改进&#xff1b;添加新的网络传输子系统&#xff0c;进行了较大的改进&#xff1b;Spark SQL 引入了一个…

[转载].SSRAM、SDRAM和Flash简要介绍

转CalmBright兄的博文&#xff1a;http://www.cnblogs.com/CalmBright/archive/2009/07/19/1526569.html Abstract 在用NIos II 调试sdram遇到了其容量计算的问题&#xff0c;现介绍如下 Introduction 问题1&#xff1a;什么是DRAM、SRAM、SDRAM&#xff1f; 答&#xff1a;名词…