翼度科技»论坛 编程开发 .net 查看内容

ORM核心功能之导航属性- EFCore和 SqlSugar

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
导航属性

导航属性是作为.NET ORM核心功能中的核心,在SqlSugar没有支持导航属性前,都说只是一个高级DbHelper, 经过3年的SqlSugar重构已经拥有了一套
非常成熟的导航属性体系,本文不是重点讲SqlSugar而是重点讲导航属性的作用,让更多写Sql人还未使用ORM的人了解到ORM的作用。
 
1.复杂的查询过滤

用户根据权限过滤,用户根据组织过滤 等这种多对多情况用SQL就相当复杂 ,例如:用SQL写一个多对多过滤就要联3个表(主表 中间表 从表),如果
Where中用到多个多对多或者嵌套多对多那写SQL简直就是恶梦 (一对多和一对一差也有提升并,没有多对多明显)
  1. //EF CORE查询
  2. var Persons= dbContext.Person //需要定义DbSet才能点出来
  3. .Where(it=>it.Files.Any(y=>y.ChildFiles.Any(s=>s.name=="A"))).ToList()
  4. //SqlSugar 查询
  5. var Persons= dbContext.Queryable<Person>()
  6. .Where(it=>it.Files.Any(y=>y.ChildFiles.Any(s=>s.name=="A"))).ToList()
复制代码
用SQL写如下:
  1. SELECT p.*
  2. FROM Person p
  3. WHERE EXISTS (
  4.   SELECT 1
  5.   FROM PersonFile pf
  6.   INNER JOIN File f ON pf.FileId = f.FileId
  7.   INNER JOIN PersonFile pf2 ON f.FileId = pf2.FileId
  8.   WHERE pf.PersonId = p.PersonId
  9.     AND pf2.PersonId IN (
  10.       SELECT p2.PersonId
  11.       FROM Person p2
  12.       INNER JOIN PersonFile pf3 ON p2.PersonId = pf3.PersonId
  13.       INNER JOIN File f2 ON pf3.FileId = f2.FileId
  14.       WHERE f2.name = 'A'
  15.     )
  16. )
复制代码
像SAAS系统这种多对多用的非常多,特别在组织、用户、角色、文件等无处理不在,这也是为什么要用ORM的原因
 
2.复杂的表单提交

如果您的人事管理需要包含更多的信息,例如学历和工作经验等字段,您可以在代码中添加相应的实体和关联。
假设您有以下实体:人员(Person)、部门(Department)、职位(Position)、学历(Education)和工作经验(WorkExperience)。
  1. var person = new Person
  2. {
  3.     // 设置人员属性...
  4.     Department = new Department
  5.     {
  6.         // 设置部门属性...
  7.     },
  8.     Position = new Position
  9.     {
  10.         // 设置职位属性...
  11.     },
  12.     Education = new Education
  13.     {
  14.         // 设置教育属性...
  15.     },
  16.     WorkExperience = new WorkExperience
  17.     {
  18.         // 设置工作经历属性...
  19.     }
  20. };
复制代码
代码如下:
  1. //SqlSugar 导航插入
  2. db.InsertNav(person)
  3. .Include(z1 => z1.Department)  
  4. .Include(z1 => z1.Position)
  5. .Include(z1 => z1.Education)  
  6. .Include(z1 => z1.WorkExperience)  
  7. .ExecuteCommand();//导航插入 一句就能搞定,先插入主表,然后在根据主表的主键在插入从表,特别是自增列用导航代码清爽很多
复制代码
 
3.多层级结构的查询

因为Sql本身就不支持对多层级结构查询,所以不用ORM想实现高性能的多层级结构是需要花大量精力去优化和写代码的
  1. //EF CORE查询
  2. var Persons= dbContext.Person
  3. .Include(z1 => z1.Department)
  4. .Include(z1 => z1.Position)
  5. .Include(z1 => z1.Education)
  6. .Include(z1 => z1.WorkExperience).ToList()
复制代码
 
EF Core导航属性配置

EF多对多
  1. public class Student
  2. {
  3.     public int StudentId { get; set; }
  4.     public string StudentName { get; set; }
  5.     // 其他学生属性...
  6.     public virtual ICollection<Course> Courses { get; set; }
  7. }
  8. public class Course
  9. {
  10.     public int CourseId { get; set; }
  11.     public string CourseName { get; set; }
  12.     // 其他课程属性...
  13.     public virtual ICollection<Student> Students { get; set; }
  14. }
  15. public class StudentCourse
  16. {
  17. public int CourseId { get; set; }
  18.   public int StudentId { get; set; }
  19. }
  20. // 配置多对多关系
  21. protected override void OnModelCreating(ModelBuilder modelBuilder)
  22. { modelBuilder.Entity<Student>()
  23. .HasMany(s => s.Courses)
  24. .WithMany(c => c.Students) .UsingEntity(j => j.ToTable("StudentCourse"));
  25. }
复制代码
EF一对多和一对一
  1. public class Department
  2. {
  3.     public int DepartmentId { get; set; }
  4.     public string DepartmentName { get; set; }
  5.     // 其他部门属性...
  6.     public virtual ICollection<Employee> Employees { get; set; }
  7. }
  8. public class Employee
  9. {
  10.     public int EmployeeId { get; set; }
  11.     public string EmployeeName { get; set; }
  12.     // 其他员工属性...
  13.     public int DepartmentId { get; set; }
  14.     public virtual Department Department { get; set; }
  15. }
  16. // 配置一对多关系
  17. protected override void OnModelCreating(ModelBuilder modelBuilder)
  18. {
  19.     modelBuilder.Entity<Department>()
  20.         .HasMany(d => d.Employees)
  21.         .WithOne(e => e.Department)
  22.         .HasForeignKey(e => e.DepartmentId);
  23. }
复制代码
 
SqlSugar导航属性配置

SqlSugar多对多
  1. //实体
  2. public class ABMapping1
  3. {
  4.     [SugarColumn(IsPrimaryKey = true)]//中间表可以不是主键
  5.     public int AId { get; set; }
  6.     [SugarColumn(IsPrimaryKey = true)]//中间表可以不是主键
  7.     public int BId { get; set; }
  8. }
  9. public class A1
  10. {
  11.     [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
  12.     public int Id { get; set; }
  13.     public string Name { get; set; }
  14.     [Navigate(typeof(ABMapping1), nameof(ABMapping1.AId), nameof(ABMapping1.BId))]//注意顺序
  15.     public List<B1> BList { get; set; }//只能是null不能赋默认值
  16. }
  17. public class B1
  18. {
  19.     [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
  20.     public int Id { get; set; }
  21.     public string Name { get; set; }
  22.     [Navigat(typeof(ABMapping1), nameof(ABMapping1.BId), nameof(ABMapping1.AId))]//注意顺序
  23.     public List<A1> AList { get; set; }//只能是null不能赋默认值
  24. }  
复制代码
 
Sqlugar一对一和一对多
  1. //实体
  2. public class StudentA
  3. {
  4.     [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
  5.     public int StudentId { get; set; }
  6.     public string Name { get; set; }public int SchoolId { get; set; }
  7.     [Navigate(NavigateType.OneToOne, nameof(SchoolId))]//一对一 SchoolId是StudentA类里面的
  8.     public SchoolA SchoolA { get; set; } //不能赋值只能是null
  9. }
  10. public class SchoolA
  11. {
  12.     [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
  13.     public int Id{ get; set; }
  14.     public string SchoolName { get; set; }
  15.    [Navigate(NavigateType.OneToMany, nameof(BookA.studenId))]//一对多 BookA表中的studenId
  16.     public List<BookA> Books { get; set; }//注意禁止给books手动赋值
  17. }
复制代码
 
SqlSugar 2023年导航新功能

SqlSugar 第一层自动导航
  1. var list3 = db.Queryable<UnitaStudentA>()
  2.               .IncludesAllFirstLayer().ToList();//有重载可以排除不想要的
  3.                
  4.                //排除说明:
  5.                //IncludesAllFirstLayer(nameof(UnitaStudentA.ProjectPhases))
  6.                //这样就是排除ProjectPhases的导航属性
  7.                //可以排除多个
  8.                //IncludesAllFirstLayer("a","b")
  9.                
  10. //自动导航如果有重复的情况: 谁在前面执行哪个
  11. var list3 = db.Queryable<UnitaStudentA>()
  12.               .Includes(it=>it.Order.Where(s=>s.id==1).ToList())
  13.               .IncludesAllFirstLayer().ToList();//自动导航和Order重复
  14.                
  15. //根据名字导航              
  16. db.Queryable<Order>()
  17. //等同于Includes(it=>it.ProjectPhases)
  18. .IncludesByNameString(nameof(Order.ProjectPhases)).ToList()
复制代码
SqlSugar第二层半自动
  1. //自动写法,Books下面的A和B都会查询出来
  2. .IncludesAllSecondLayer(x=>x.Books)  //自动只能有这么多层次,更深层级需要手动写法
  3. //手动写法
  4. .Includes(x => x.Books,x=>x.A)
  5. .Includes(x => x.Books,x=>x.B)
复制代码
SqlSugar导航DTO转换

在前二年SqlSugar导航只能说够用,并不算好用,今年重点将导航DTO进行了强化
  1. //简单的用法   5.1.4.71
  2. var list = db.Queryable<Student_004>()
  3.         .Includes(x => x.books)
  4.         .Select(x => new Student_004DTO
  5.            {
  6.              books = x.books
  7.               
  8.             }, true)//true是自动映射其他属性,匿名对象需要手动
  9.            .ToList();
  10.                   
  11.                  
  12. //Mapster转换  5.1.4.71
  13. var list = db.Queryable<Student_004>()
  14.         .Includes(x => x.books)
  15.         .Select(x => new Student_004DTO
  16.          {
  17.            name=x.Name,
  18.            books = x.books.Adapt<List<BooksDTO>>() //导航对象用 Mapster转换 (NUGET安装)
  19.          })
  20.         .ToList();            
  21. //DTO中用方法  5.1.4.71
  22. var list = db.Queryable<Student_004>()
  23.          .Includes(x => x.books)
  24.          .Select(x => new Student_004DTO
  25.                  {
  26.                    name=x.Name,
  27.                    //可以是C#任何方法结尾
  28.                    //比如 b.books.FirstOrDefault() (因为是C#方法First没有值会报错)
  29.                    bookIds=x.books.Select(it=>it.id).ToList()
  30.                  })
  31.                 .ToList();   
  32. //联表查询用DTO写法  5.1.4.71           
  33. var list5= db.Queryable<Student_004>()
  34.            .Includes(x => x.school_001, x => x.rooms)
  35.            .Includes(x => x.books)
  36.            .LeftJoin<Order>((x, y) => x.Id==y.sid)
  37.            .Select((x,y) => new Student_004DTO
  38.            {
  39.                SchoolId = x.SchoolId,
  40.                books = x.books,
  41.                school_001 = x.school_001,
  42.                Name=y.Name
  43.            })
  44.            .ToList();
复制代码
当你遇到繁琐的数据库操作时,.NET SQLSugar就像是一双温暖的手,帮你轻松解决难题。它是一个强大的工具,让你的数据库管理变得更简单、更高效。下载.NET SQLSugar吧,让它成为你的数据之路上的得力助手,让你的编程之旅充满感动与喜悦!
原码下载: https://github.com/DotNetNext/SqlSugar
 
总结:

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

来源:https://www.cnblogs.com/sunkaixuan/archive/2023/06/05/17457497.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具