前言

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

Id ParentId Name
1 null 总公司
2 1 分公司1
3 1 分公司2
4 2 部门A
5 4 小组X
6 4 小组Y

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

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

HierarchyId

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

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

Id Name
/ 总公司
/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“,记住我!

使用EF Core操作层次结构数据相关推荐

  1. ef导入oracle数据类型不正确,EF Core操作Oracle踩坑记

    EF(Entity Framework)是微软标志性且成熟的ORM,从之前的.NET Framework时代就已经很常见了,但是给人的感觉还是偏"重",性能被不少人吐槽,倒是像Da ...

  2. ASP.NET Core 开发-Entity Framework (EF) Core 1.0 Database First

    ASP.NET Core 开发-Entity Framework Core 1.0 Database First,ASP.NET Core 1.0 EF Core操作数据库. Entity Frame ...

  3. 国产化之路-统信UOS /Nginx /Asp.Net Core+ EF Core 3.1/达梦DM8实现简单增删改查操作

    引言 经过前期的准备工作,.net core 3.1的运行环境和WEB服务器已经搭建完毕,这里需要注意一下,达梦DM8数据库对于Entity Framework Core 3.1 的驱动在NuGet官 ...

  4. [小技巧]EF Core中如何获取上下文中操作过的实体

    原文地址:https://www.cnblogs.com/lwqlun/p/10576443.html 作者:Lamond Lu 源代码:https://github.com/lamondlu/EFC ...

  5. MySQL在EF Core下的Scaffolding操作

    Pomelo于2016年11月22日发布的MySQL for ef core中,增加了DbContext Scaffolding的支持,这项功能是让开发者可以从现有的数据库中提取表.列.索引及外键成为 ...

  6. javaweb简单的登录增删改查系统_国产化之路统信UOS /Nginx /Asp.Net Core+ EF Core 3.1/达梦DM8实现简单增删改查操作...

    引言 经过前期的准备工作,.net core 3.1的运行环境和WEB服务器已经搭建完毕,这里需要注意一下,达梦DM8数据库对于Entity Framework Core 3.1 的驱动在NuGet官 ...

  7. mysql多租户schema复制,Asp.net core下利用EF core实现从数据实现多租户(3): 按Schema分离 附加:EF Migration 操作...

    前言 前段时间写了EF core实现多租户的文章,实现了根据数据库,数据表进行多租户数据隔离. 今天开始写按照Schema分离的文章. 其实还有一种,是通过在数据表内添加一个字段做多租户的,但是这种模 ...

  8. efcore 实体配置_C# 数据操作系列 - 7. EF Core 导航属性配置

    在上一篇,大概介绍了Entity Framework Core关于关系映射的逻辑.在上一篇中留下了EF的外键映射没有说,也就是一对一,一对多,多对一,多对多的关系等.这一篇将为大家细细分析一下,如何设 ...

  9. EF Core学习笔记:反向工程 + 底层操作数据库原理

    EF core三种建模模式:DB first / Model first / Code first 反向工程:根据数据库表来反向生成实体类 应用场景:通过旧的数据库生成新的项目 命令: Scaffol ...

最新文章

  1. POJ 3268 D-Silver Cow Party
  2. 《数学之美》第20章 不要把鸡蛋都放到一个篮子里--谈谈最大熵模型
  3. 《高阶Perl》——导读
  4. Jsp在Web.xml中的配置
  5. JDK、JRE、JVM三者间的关系(有图)
  6. centos下实现程序开机自启动(tomcat为例)
  7. Mysql商品和图片表_【mysql】数据库设计模式:多个图片怎么和商品关联
  8. java编写WordCound的Spark程序,Scala编写wordCound程序
  9. 对 java 同步锁 以及 级别升级的 理解
  10. Shiro 登录、退出、校验是否登录涉及到的Session和Cookie
  11. 企业微信_新建自建H5小程序应用及主页与菜单设置
  12. java tls 证书_在使用Java 8重新协商TLS_1.2期间,服务器证书更改受到限制
  13. Java—File类详解及实践
  14. CGGeometry.h详解
  15. JSP指示元素%@ % 与指示类型
  16. 互联网架构设计漫谈 (4)-你知道微服务的“分与合”
  17. Spring Boot加载指定属性文件
  18. Visual Studio 2015开发Android App问题集锦
  19. android https双向认证
  20. [转载] python 去除字符串中指定字符

热门文章

  1. HYDRAstor:可扩展的二级存储
  2. 关于java连接sqlserver2000 和sqlserver2005的初识
  3. 让你一周变聪明的大脑保健操
  4. 乘基取整法是什么_十进制小数转二进制小数乘2取整法的直观理解
  5. MybatisPlus 通用枚举无法正确取值
  6. Oracle服务器修改IP后
  7. war部署到tomcat
  8. 大型网站架构演化(二)——应用服务和数据服务分离
  9. IDA64 Fatal error before kernel init
  10. 设计模式学习笔记(十七)——Command命令模式