自研ORM框架 实现类似EF Core Include 拆分查询 支持自定义条件、排序、选择
Baozi, I'm Mr.Zhong I like to brush TikTok, I know that anchors like to call it that, haha!
Recently, I haven't been so busy, and it took almost a day to add some APIs to the self-developed ORM framework to perfectly implement the Include query
宝子们,我是 Mr.Zhong 喜欢刷抖音都知道 主播都喜欢这么叫,哈哈!
最近没那么忙了,抽空给自研的ORM 框架新增一些API 花了将近一天的时间 完美实现 Include 查询
一、接口定义
1 /// <summary>
2 /// 包括接口类
3 /// </summary>
4 /// <typeparam name="T"></typeparam>
5 /// <typeparam name="TProperty"></typeparam>
6 public interface IInclude<T, TProperty> : IQuery<T> where TProperty : class, new()
7 {
8 /// <summary>
9 /// Ado
10 /// </summary>
11 IAdo Ado { get; }
12 }
二、接口实现
1 /// <summary>
2 /// 包括实现类
3 /// </summary>
4 /// <typeparam name="T"></typeparam>
5 public class IncludeProvider<T, TProperty> : QueryProvider<T>, IInclude<T, TProperty> where TProperty : class, new()
6 {
7 /// <summary>
8 /// Ado
9 /// </summary>
10 public IAdo Ado { get; }
11
12 /// <summary>
13 /// 构造方法
14 /// </summary>
15 /// <param name="ado"></param>
16 /// <param name="queryBuilder">查询构建</param>
17 public IncludeProvider(IAdo ado, IQueryBuilder queryBuilder) : base(ado, queryBuilder)
18 {
19 this.Ado = ado;
20 }
21 }
三、扩展方法实现 还可以扩展很多功能 只有你想不到,没有...
1 /// <summary>
2 /// 包括扩展类
3 /// </summary>
4 public static class IncludeExtensions
5 {
6 /// <summary>
7 /// 然后包括
8 /// </summary>
9 /// <typeparam name="T"></typeparam>
10 /// <typeparam name="TPreviousProperty"></typeparam>
11 /// <param name="include">包括</param>
12 /// <returns></returns>
13 public static IInclude<T, TPreviousProperty> Visit<T, TPreviousProperty>(this IInclude<T, List<TPreviousProperty>> include) where TPreviousProperty : class, new()
14 {
15 return new IncludeProvider<T, TPreviousProperty>(include.Ado, include.QueryBuilder);
16 }
17
18 /// <summary>
19 /// 然后包括
20 /// </summary>
21 /// <typeparam name="T"></typeparam>
22 /// <typeparam name="TProperty"></typeparam>
23 /// <param name="include">包括</param>
24 /// <param name="expression">表达式</param>
25 /// <returns></returns>
26 public static IInclude<T, TProperty> ThenInclude<T, TPreviousProperty, TProperty>(this IInclude<T, List<TPreviousProperty>> include, Expression<Func<TPreviousProperty, TProperty>> expression) where TProperty : class, new()
27 {
28 return new IncludeProvider<T, TProperty>(include.Ado, include.QueryBuilder);
29 }
30
31 /// <summary>
32 /// 条件
33 /// </summary>
34 /// <typeparam name="T"></typeparam>
35 /// <typeparam name="TProperty"></typeparam>
36 /// <param name="include">包括</param>
37 /// <param name="expression">表达式</param>
38 /// <returns></returns>
39 public static IInclude<T, TProperty> Where<T, TProperty>(this IInclude<T, TProperty> include, Expression<Func<T, TProperty, bool>> expression) where TProperty : class, new()
40 {
41 var queryBuilder = include.QueryBuilder.IncludeInfos.Last().QueryBuilder;
42
43 queryBuilder.EntityDbMapping.Alias = expression.Parameters[0]?.Name;
44 include.QueryBuilder.IncludeInfos.Last().EntityDbMapping.Alias = expression.Parameters[1]?.Name;
45
46 var result = expression.ResolveSql(new ResolveSqlOptions()
47 {
48 DbType = include.Ado.DbOptions.DbType,
49 ResolveSqlType = ResolveSqlType.Where,
50 ParameterIndex = queryBuilder.DbParameters.Count + 1
51 });
52
53 queryBuilder.Where.Add(result.SqlString);
54 queryBuilder.DbParameters.AddRange(result.DbParameters);
55 return include;
56 }
57
58 /// <summary>
59 /// 排序
60 /// </summary>
61 /// <typeparam name="T"></typeparam>
62 /// <typeparam name="TProperty"></typeparam>
63 /// <param name="include">包括</param>
64 /// <param name="orderFields">排序字段</param>
65 /// <param name="orderByType">排序类型</param>
66 /// <returns></returns>
67 public static IInclude<T, TProperty> OrderBy<T, TProperty>(this IInclude<T, TProperty> include, List<string> orderFields, OrderByType orderByType = OrderByType.ASC) where TProperty : class, new()
68 {
69 var queryBuilder = include.QueryBuilder.IncludeInfos.Last().QueryBuilder;
70
71 queryBuilder.OrderBy.Add($"{string.Join(",", orderFields)} {orderByType}");
72 return include;
73 }
74
75 /// <summary>
76 /// 排序
77 /// </summary>
78 /// <typeparam name="T"></typeparam>
79 /// <typeparam name="TProperty"></typeparam>
80 /// <param name="include">包括</param>
81 /// <param name="expression">表达式</param>
82 /// <param name="orderByType">排序类型</param>
83 /// <returns></returns>
84 public static IInclude<T, TProperty> OrderBy<T, TProperty>(this IInclude<T, TProperty> include, Expression<Func<T, TProperty, object>> expression, OrderByType orderByType = OrderByType.ASC) where TProperty : class, new()
85 {
86 var queryBuilder = include.QueryBuilder.IncludeInfos.Last().QueryBuilder;
87
88 queryBuilder.EntityDbMapping.Alias = expression.Parameters[0]?.Name;
89 include.QueryBuilder.IncludeInfos.Last().EntityDbMapping.Alias = expression.Parameters[1]?.Name;
90
91 var result = expression.ResolveSql(new ResolveSqlOptions()
92 {
93 DbType = include.Ado.DbOptions.DbType,
94 ResolveSqlType = ResolveSqlType.OrderBy
95 });
96
97 queryBuilder.OrderBy.Add($"{result.SqlString} {orderByType}");
98 return include;
99 }
100
101 /// <summary>
102 /// 选择
103 /// </summary>
104 /// <typeparam name="T"></typeparam>
105 /// <typeparam name="TProperty"></typeparam>
106 /// <param name="include">包括</param>
107 /// <param name="expression">表达式</param>
108 /// <returns></returns>
109 public static IInclude<T, TProperty> Select<T, TProperty>(this IInclude<T, TProperty> include, Expression<Func<T, TProperty, object>> expression) where TProperty : class, new()
110 {
111 var queryBuilder = include.QueryBuilder.IncludeInfos.Last().QueryBuilder;
112
113 queryBuilder.EntityDbMapping.Alias = expression.Parameters[0]?.Name;
114 include.QueryBuilder.IncludeInfos.Last().EntityDbMapping.Alias = expression.Parameters[1]?.Name;
115
116 var result = expression.ResolveSql(new ResolveSqlOptions()
117 {
118 DbType = include.Ado.DbOptions.DbType,
119 ResolveSqlType = ResolveSqlType.NewAs
120 });
121
122 queryBuilder.Columns = result.SqlString;
123 queryBuilder.DbParameters.AddRange(result.DbParameters);
124 return include;
125 }
126
127 }
128 }
四、使用示例
1 var data = await db.Query<Category>().Include(a => a.Products).Visit().OrderBy((a1, a2) => a2.CreateTime, OrderByType.DESC).ToListAsync();
五、生成的SQL语句
SELECT a1.`CategoryId`,a1.`CategoryName`,a2.`ProductId`,a2.`CategoryId`,a2.`ProductCode`,a2.`ProductName`,a2.`DeleteMark`,a2.`CreateTime`,a2.`ModifyTime`,a2.`Custom1`,a2.`Custom2`,a2.`Custom3`,a2.`Custom4`,a2.`Custom5`,a2.`Custom6`,a2.`Custom7`,a2.`Custom8`,a2.`Custom9`,a2.`Custom10`,a2.`Custom11`,a2.`Custom12` FROM `Category` `a1`
INNER JOIN `Product` `a2` ON `a1`.`CategoryId` = `a2`.`CategoryId`
WHERE `a1`.`CategoryId` = @CategoryId
ORDER BY `a2`.`CreateTime` DESC
翻译
搜索
复制
自研ORM框架 实现类似EF Core Include 拆分查询 支持自定义条件、排序、选择的更多相关文章
- .Net 常用ORM框架对比:EF Core、FreeSql、SqlSuger
前言: 最近由于工作需要,需要选用一种ORM框架,也因此对EF Core.FreeSql.SqlSuger作简单对比.个人认为各有有优势,存在即合理,不然早就被淘汰了是吧,所以如何选择因人而议.因项目 ...
- 深入理解 EF Core:使用查询过滤器实现数据软删除
原文:https://bit.ly/2Cy3J5f 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能会去除一些本人实在不知道如何组织 ...
- EF Core 的关联查询
0 前言 本文会列举出 EF Core 关联查询的方法: 在第一.二.三节中,介绍的是 EF Core 的基本能力,在实体中配置好关系,即可使用,且其使用方式,与编程思维吻合,是本文推荐的方式. 第四 ...
- EF Core 使用编译查询提高性能
今天,我将向您展示这些EF Core中一个很酷的功能,通过使用显式编译的查询,提高查询性能. 不过在介绍具体内容之前,需要说明一点,EF Core已经对表达式的编译使用了缓存:当您的代码需要重用以前执 ...
- EF Core 2.0 已经支持自动生成父子关系表的实体
现在我们在SQL Server数据库中有Person表如下: CREATE TABLE [dbo].[Person]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [Cr ...
- EF core的原生SQL查询以及用EF core进行分页查询遇到的问题
在用.net core进行数据库访问,需要处理一些比较复杂的查询,就不得不用原生的SQL查询了,然而EF Core 和EF6 的原生sql查询存在很大的差异. 在EF6中我们用SqlQuery和Exe ...
- ORM框架学习之EF
首先推荐一篇很好的EF文章翻译,可以系统的学习一遍. <Entity Framework 6 Recipes>中文翻译系列 EF使用体会 优点: 可以省去Ado.net复杂的管道连接代码. ...
- EF Core 快速上手——EF Core 入门
EF Core 快速上手--EF Core 介绍 本章导航 从本书你能学到什么 对EF6.x 程序员的一些话 EF Core 概述 1.3.1 ORM框架的缺点 第一个EF Core应用 本文是对 ...
- EntityFramework Core 3.0查询
前言 随着.NET Core 3.0的发布,EF Core 3.0也随之正式发布,关于这一块最近一段时间也没太多去关注,陆续会去对比之前版本有什么变化没有,本节我们来看下两个查询. 分组 我们知道在E ...
- Mego(2) - NET主流ORM框架分析
接上文我们测试了各个ORM框架的性能,大家可以很直观的看到各个ORM框架与原生的ADO.NET在境删改查的性能差异.这里和大家分享下我对ORM框架的理解及一些使用经验. ORM框架工作原理 典型ORM ...
随机推荐
- Prometheus 监控报警系统 AlertManager 之邮件告警
转载自:https://cloud.tencent.com/developer/article/1486483 文章目录1.Prometheus & AlertManager 介绍2.环境.软 ...
- 5_项目实战MyShop
一. 网上商城 1.1 商城类别 B2B 商家对商家 B2C 商家对客户 C2C 客户对客户 O2O 线上线下相结合 1.2 商城常见模块 后台常见功能模块 商品管理 包括后台商品库存管理, 上货, ...
- 影响 erp 系统实施成功的因素是什么?
影响ERP系统实施成功的因素很多,主要有以下几点:企业一把手是否大力支持.实施顾问是否专业负责.ERP系统是否强大灵活且适用三个方面!没有企业一把手的大力支持,ERP的应用基本上不可能获得成功.ERP ...
- C#并发编程-1 并发编程概述
一 并发编程简介 1.1 关于并发和并行 并发和并行的概念: 并发:(Concurrent),在某个时间段内,如果有多个任务执行,即有多个线程在操作时,如果系统只有一个CPU,则不能真正同时进行一个以 ...
- 驱动开发:通过Async反向与内核通信
在前几篇文章中给大家具体解释了驱动与应用层之间正向通信的一些经典案例,本章将继续学习驱动通信,不过这次我们学习的是通过运用Async异步模式实现的反向通信,反向通信机制在开发中时常被用到,例如一个杀毒 ...
- SpringBoot课程学习(三)
一.YAML格式的基本语法 (1)格式: 大小写敏感 数据值前边必须有空格,作为分隔符 使用缩进表示层级关系 缩进时不允许使用Tab键,只允许使用空格(各个系统 Tab对应的 空格数目可能不同,导致层 ...
- P3261 [JLOI2015]城池攻占 (左偏树+标记下传)
左偏树还是满足堆的性质,节点距离就是离最近的外节点(无左或者右儿子 或者二者都没有)的距离,左偏性质就是一个节点左儿子的距离不小于右儿子,由此得:节点距离等于右儿子的距离+1. 本题就是对于每个节点 ...
- 生产系统CPU飙高问题排查
现状 生产系统CPU占用过高,并且进行了报警 排查方法 执行top命令,查看是那个进程导致的,可以确定是pid为22168的java应用导致的 执行top -Hp命令,查看这个进程的那个线程导致cpu ...
- .NET 6学习笔记(4)——如何在.NET 6的Desktop App中使用Windows Runtime API
Windows Runtime API是当初某软为了区别Win32 API,力挺UWP而创建的另一套Windows 10专用的API集合.后来因为一些原因,UWP没火.为了不埋没很有价值的Window ...
- 知识图谱-生物信息学-医学顶刊论文(Bioinformatics-2021)-SumGNN:通过有效的KG聚集进行多类型DDI预测
3.(2021.3.26)Bioinformatics-SumGNN:通过有效的KG聚集进行多类型DDI预测 论文标题: SumGNN: multi-typed drug interaction pr ...