导航属性

导航属性是作为ORM核心功能中的核心,在SqlSugar没有支持导航属性前,都说只是一个高级DbHelper, 经过3年的SqlSugar重构已经拥有了一套

非常成熟的导航属性体系,本文不是重点讲SqlSugar而是重点讲导航属性的作用,让更多写Sql人还未使用ORM的人了解到ORM的作用。

1.复杂的查询过滤

用户根据权限过滤,用户根据组织过滤 等这种多对多情况用SQL就相当复杂 ,例如:用SQL写一个多对多过滤就要联3个表(主表 中间表 从表),如果

Where中用到多个多对多或者嵌套多对多那写SQL简直就是恶梦 (一对多和一对一差也有提升并,没有多对多明显)

//EF CORE查询
var Persons= dbContext.Person //需要定义DbSet才能点出来
.Where(it=>it.Files.Any(y=>y.ChildFiles.Any(s=>s.name=="A"))).ToList() //SqlSugar 查询
var Persons= dbContext.Queryable<Person>()
.Where(it=>it.Files.Any(y=>y.ChildFiles.Any(s=>s.name=="A"))).ToList()

用SQL写如下:

SELECT p.*
FROM Person p
WHERE EXISTS (
SELECT 1
FROM PersonFile pf
INNER JOIN File f ON pf.FileId = f.FileId
INNER JOIN PersonFile pf2 ON f.FileId = pf2.FileId
WHERE pf.PersonId = p.PersonId
AND pf2.PersonId IN (
SELECT p2.PersonId
FROM Person p2
INNER JOIN PersonFile pf3 ON p2.PersonId = pf3.PersonId
INNER JOIN File f2 ON pf3.FileId = f2.FileId
WHERE f2.name = 'A'
)
)

像SAAS系统这种多对多用的非常多,特别在组织、用户、角色、文件等无处理不在,这也是为什么要用ORM的原因

2.复杂的表单提交

如果您的人事管理需要包含更多的信息,例如学历和工作经验等字段,您可以在代码中添加相应的实体和关联。

假设您有以下实体:人员(Person)、部门(Department)、职位(Position)、学历(Education)和工作经验(WorkExperience)。

var person = new Person
{
// 设置人员属性...
Department = new Department
{
// 设置部门属性...
},
Position = new Position
{
// 设置职位属性...
},
Education = new Education
{
// 设置教育属性...
},
WorkExperience = new WorkExperience
{
// 设置工作经历属性...
}
};

代码如下:

//SqlSugar 导航插入
db.InsertNav(person)
.Include(z1 => z1.Department)
.Include(z1 => z1.Position)
.Include(z1 => z1.Education)
.Include(z1 => z1.WorkExperience)
.ExecuteCommand();//导航插入 一句就能搞定,先插入主表,然后在根据主表的主键在插入从表,特别是自增列用导航代码清爽很多

3.多层级结构的查询

因为Sql本身就不支持对多层级结构查询,所以不用ORM想实现高性能的多层级结构是需要花大量精力去优化和写代码的

//EF CORE查询
var Persons= dbContext.Person
.Include(z1 => z1.Department)
.Include(z1 => z1.Position)
.Include(z1 => z1.Education)
.Include(z1 => z1.WorkExperience).ToList()

EF Core导航属性配置

EF多对多

public class Student
{
public int StudentId { get; set; }
public string StudentName { get; set; }
// 其他学生属性... public virtual ICollection<Course> Courses { get; set; }
} public class Course
{
public int CourseId { get; set; }
public string CourseName { get; set; }
// 其他课程属性... public virtual ICollection<Student> Students { get; set; }
} public class StudentCourse
{
public int CourseId { get; set; }
public int StudentId { get; set; } }
// 配置多对多关系
protected override void OnModelCreating(ModelBuilder modelBuilder)
{ modelBuilder.Entity<Student>()
.HasMany(s => s.Courses)
.WithMany(c => c.Students) .UsingEntity(j => j.ToTable("StudentCourse"));
}

EF一对多和一对一

public class Department
{
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
// 其他部门属性... public virtual ICollection<Employee> Employees { get; set; }
} public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
// 其他员工属性... public int DepartmentId { get; set; }
public virtual Department Department { get; set; }
} // 配置一对多关系
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Department>()
.HasMany(d => d.Employees)
.WithOne(e => e.Department)
.HasForeignKey(e => e.DepartmentId);
}

SqlSugar导航属性配置

SqlSugar多对多

//实体
public class ABMapping1
{
[SugarColumn(IsPrimaryKey = true)]//中间表可以不是主键
public int AId { get; set; }
[SugarColumn(IsPrimaryKey = true)]//中间表可以不是主键
public int BId { get; set; }
}
public class A1
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
[Navigate(typeof(ABMapping1), nameof(ABMapping1.AId), nameof(ABMapping1.BId))]//注意顺序
public List<B1> BList { get; set; }//只能是null不能赋默认值
}
public class B1
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
[Navigat(typeof(ABMapping1), nameof(ABMapping1.BId), nameof(ABMapping1.AId))]//注意顺序
public List<A1> AList { get; set; }//只能是null不能赋默认值
}

Sqlugar一对一和一对多

//实体
public class StudentA
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int StudentId { get; set; }
public string Name { get; set; }public int SchoolId { get; set; }
[Navigate(NavigateType.OneToOne, nameof(SchoolId))]//一对一 SchoolId是StudentA类里面的
public SchoolA SchoolA { get; set; } //不能赋值只能是null
}
public class SchoolA
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id{ get; set; }
public string SchoolName { get; set; }
[Navigate(NavigateType.OneToMany, nameof(BookA.studenId))]//一对多 BookA表中的studenId
public List<BookA> Books { get; set; }//注意禁止给books手动赋值 }

SqlSugar 2023年导航新功能

SqlSugar 第一层自动导航

var list3 = db.Queryable<UnitaStudentA>()
.IncludesAllFirstLayer().ToList();//有重载可以排除不想要的 //排除说明:
//IncludesAllFirstLayer(nameof(UnitaStudentA.ProjectPhases))
//这样就是排除ProjectPhases的导航属性
//可以排除多个
//IncludesAllFirstLayer("a","b") //自动导航如果有重复的情况: 谁在前面执行哪个
var list3 = db.Queryable<UnitaStudentA>()
.Includes(it=>it.Order.Where(s=>s.id==1).ToList())
.IncludesAllFirstLayer().ToList();//自动导航和Order重复 //根据名字导航
db.Queryable<Order>()
//等同于Includes(it=>it.ProjectPhases)
.IncludesByNameString(nameof(Order.ProjectPhases)).ToList()

SqlSugar第二层半自动

//自动写法,Books下面的A和B都会查询出来
.IncludesAllSecondLayer(x=>x.Books) //自动只能有这么多层次,更深层级需要手动写法 //手动写法
.Includes(x => x.Books,x=>x.A)
.Includes(x => x.Books,x=>x.B)

SqlSugar导航DTO转换

在前二年SqlSugar导航只能说够用,并不算好用,今年重点将导航DTO进行了强化

//简单的用法   5.1.4.71
var list = db.Queryable<Student_004>()
.Includes(x => x.books)
.Select(x => new Student_004DTO
{
books = x.books }, true)//true是自动映射其他属性,匿名对象需要手动
.ToList(); //Mapster转换 5.1.4.71
var list = db.Queryable<Student_004>()
.Includes(x => x.books)
.Select(x => new Student_004DTO
{
name=x.Name,
books = x.books.Adapt<List<BooksDTO>>() //导航对象用 Mapster转换 (NUGET安装)
})
.ToList(); //DTO中用方法 5.1.4.71
var list = db.Queryable<Student_004>()
.Includes(x => x.books)
.Select(x => new Student_004DTO
{
name=x.Name,
//可以是C#任何方法结尾
//比如 b.books.FirstOrDefault() (因为是C#方法First没有值会报错)
bookIds=x.books.Select(it=>it.id).ToList()
})
.ToList(); //联表查询用DTO写法 5.1.4.71
var list5= db.Queryable<Student_004>()
.Includes(x => x.school_001, x => x.rooms)
.Includes(x => x.books)
.LeftJoin<Order>((x, y) => x.Id==y.sid)
.Select((x,y) => new Student_004DTO
{
SchoolId = x.SchoolId,
books = x.books,
school_001 = x.school_001,
Name=y.Name
})
.ToList();

当你遇到繁琐的数据库操作时,SQLSugar就像是一双温暖的手,帮你轻松解决难题。它是一个强大的工具,让你的数据库管理变得更简单、更高效。下载SQLSugar吧,让它成为你的数据之路上的得力助手,让你的编程之旅充满感动与喜悦!

原码下载: https://github.com/DotNetNext/SqlSugar

总结:

无论是EF CORE还是SQLSUGAR 使用了导航属性都不再需要费心写繁琐的SQL语句,只需简单地调用导航属性,便能轻松获取所需的数据。让我们一起追随这份感动,选择使用导航属性,让编程的旅途更加愉悦,让代码的世界充满美好与便捷!

ORM核心功能之导航属性- EFCore和 SqlSugar的更多相关文章

  1. FreeSql 导航属性的联级保存功能

    写在前面 FreeSql 一个款 .net 平台下支持 .net framework 4.5+..net core 2.1+ 的开源 ORM.单元测试超过3100+,正在不断吸引新的开发者,生命不息开 ...

  2. .NET ORM 导航属性【到底】可以解决什么问题?

    写在开头 从最早期入门时的单表操作, 到后来接触了 left join.right join.inner join 查询, 因为经费有限,需要不断在多表查询中折腾解决实际需求,不知道是否有过这样的经历 ...

  3. Xwork概况 XWork是一个标准的Command模式实现,并且完全从web层脱离出来。Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL – the Object Graph NavigationLanguage),IoC(Inversion of Control反转控制)容器等。 ----------------

    Xwork概况 XWork是一个标准的Command模式实现,并且完全从web层脱离出来.Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式 ...

  4. ASP.NET EF 延迟加载,导航属性延迟加载

    ASP.NET EF 延迟加载,导航属性延迟加载   EF(EntityFramework)原理:属于ORM的一种实现 通过edmx文件来查看三部分:概念模型,数据模型,映射关系,上下文DbConte ...

  5. ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪

    ASP.NET MVC深入浅出(被替换)   一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...

  6. 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  7. Spring 核心功能演示

    Spring 核心功能演示 Spring Framework 简称 Spring,是 Java 开发中最常用的框架,地位仅次于 Java API,就连近几年比较流行的微服务框架 SpringBoot, ...

  8. EF Core 三 、 骚操作 (导航属性,内存查询...)

    EF Core 高阶操作 本文之前,大家已经阅读了前面的系列文档,对其有了大概的了解 我们来看下EF Core中的一些常见高阶操作,来丰富我们业务实现,从而拥有更多的实现选择 1.EF 内存查找 wh ...

  9. 《Entity Framework 6 Recipes》中文翻译系列 (28) ------ 第五章 加载实体和导航属性之测试实体是否加载与显式加载关联实体

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-11  测试实体引用或实体集合是否加载 问题 你想测试关联实体或实体集合是否已经 ...

  10. 带连接池的netty客户端核心功能实现剖解

    带连接池的netty客户端核心功能实现剖析 带连接池的netty的客户端核心功能实现剖析 本文为原创,转载请注明出处 源码地址: https://github.com/zhangxianwu/ligh ...

随机推荐

  1. 如何用Python对股票数据进行LSTM神经网络和XGboost机器学习预测分析(附源码和详细步骤),学会的小伙伴们说不定就成为炒股专家一夜暴富了

    前言 最近调研了一下我做的项目受欢迎程度,大数据分析方向竟然排第一,尤其是这两年受疫情影响,大家都非常担心自家公司裁员或倒闭,都想着有没有其他副业搞搞或者炒炒股.投资点理财产品,未雨绸缪,所以不少小伙 ...

  2. Sound Joy最新固件3.0.0.20版本 后悔了

    不建议更新3.0.0.20版本,更新之后音质直线下降,音质变得不耐听,低音浑浊,高音刺耳,三段不均衡.单纯听个响.更新此固件之后音质已经和100多的音响持平.对标JBL 万花筒6已经变得不可能.据我观 ...

  3. 快收藏!最全GO语言实现设计模式

    https://segmentfault.com/a/1190000042859564

  4. 最新版本 Stable Diffusion 开源AI绘画工具之部署篇

    目录 AI绘画 本地环境要求 下载 Stable Diffusion 运行启动 AI绘画 关于 AI 绘画最近有多火,既然你有缘能看到这篇文章,那么相信也不需要我过多赘述了吧? 随着 AI 绘画技术的 ...

  5. 必知必会的 WebSocket 协议

    文章介绍 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它的出现使客户端和服务器之间的数据交换变得更加简单.WebSocket 通常被应用在实时性要求较高的场景,例如赛事数据. ...

  6. 二进制安装Kubernetes,一键安装脚本

    背景,最近几天闲着研究Kubernetes,发现使用手动二进制安装会有些繁琐.经过突发奇想,就出现这个脚本. 声明,该脚本不及互联网上其他大佬的一件脚本,该脚本仅仅是突发奇想编写的,希望大佬不喜勿喷. ...

  7. kubernetes核心实战(七)--- job、CronJob、Secret

    10.job任务 使用perl,做pi的圆周率计算 [root@k8s-master-node1 ~/yaml/test]# vim job.yaml [root@k8s-master-node1 ~ ...

  8. [Linux]Xmanager+Xshell远程管理桌面版CentOS物理服务器的桌面版CentOS虚拟机

    1 需求/背景 在项目现场有这么一个情况,有1台Gnome版的CentOS的物理服务器,其内运行了2台通过vmware安装的Gnome桌面版的CentOS的虚拟服务器. 按照常规做法是: 将唯一的1台 ...

  9. AutoGPT目前只是成功学大师GPT版

    一大波韭菜被收割了 最近很多人在交流对于AutoGPT的震惊和激动.AutoGPT是一个开源的应用程序,展示了GPT-4语言模型的能力.这个程序由GPT-4驱动,自主地开发和管理业务,以增加净值.它是 ...

  10. .Net 6.0 部署Linux+Nginx +PM2教程

    今天带大家将本地.Net6.0项目部署到Linux系统中,其中有用到Nginx反向代理和PM2进程管理工具,希望本偏文章能对你有所帮助,成为你成功路上的垫脚石! 背景: 在.Net 5.0横空出世之后 ...