自研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 ...
随机推荐
- 【设计模式】Java设计模式 - 命令模式
Java设计模式 - 命令模式 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目录 Ja ...
- .Net CLR GC plan_phase二叉树和Brick_table
楔子 别那么懒,勤快点.以下取自CLR PreView 7.0. 主题 GC计划阶段(plan_phase)主要就两个部分,一个是堆里面的对象构建一颗二叉树(这颗二叉树的每个节点包含了诸如对象移动信息 ...
- Hive之命令
Hive之命令 说明:此博客只记录了一些常见的hql,create/select/insert/update/delete这些基础操作是没有记录的. 一.时间级 select day -- 时间 ,d ...
- 驱动开发:内核枚举LoadImage映像回调
在笔者之前的文章<驱动开发:内核特征码搜索函数封装>中我们封装实现了特征码定位功能,本章将继续使用该功能,本次我们需要枚举内核LoadImage映像回调,在Win64环境下我们可以设置一个 ...
- flutter系列之:flutter中可以建索引的栈布局IndexedStack
目录 简介 IndexedStack简介 IndexedStack的使用 总结 简介 之前我们介绍了一个flutter的栈结构的layout组件叫做Stack,通过Stack我们可以将一些widget ...
- 什么是subsignature和return-type-substitutable
subsignature 什么是签名(signature) 方法签名组成:方法名+参数列表(参数的类型.个数.顺序) Java语言层面规定的签名是不包含返回值类型的: JVM层面规定的签名是包含返回值 ...
- 安装zabbix-agent2之ansible-playbook
zabbix被监控端安装zabbix-agent2之ansible-playbook --- - name: install agent hosts: all vars: server_host: & ...
- String基础: String两种创建对象方式的比较
字符串常量 在一般的语言中常量一旦声明则不可改变,在java中的字符串常量是以匿名对象来表示的 javaz中字符串两种定义方法: String strA= new String("hello ...
- Xpath 高级用法
xpath 高级用法 1. 匹配当前节点下的所有: .// . 表示当前 // 表示当前标签下的所有标签 注: 要配合使用 2. 匹配某标签的属性值: /@属性名称 这里以input里的value值为 ...
- 【单元测试】Junit 4(三)--Junit4断言
1.0 前言 断言(assertion)是一种在程序中的一阶逻辑(如:一个结果为真或假的逻辑判断式),目的为了表示与验证软件开发者预期的结果--当程序执行到断言的位置时,对应的断言应该为真.若断言 ...