前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SqlSugar ORM 入门篇2 【查询】 让我们实现零SQL「建议收藏」

SqlSugar ORM 入门篇2 【查询】 让我们实现零SQL「建议收藏」

作者头像
全栈程序员站长
发布于 2022-09-20 02:53:36
发布于 2022-09-20 02:53:36
2K00
代码可运行
举报
运行总次数:0
代码可运行

SqlSugar在查询的功能是非常强大的,多表查询、分页查询 、 一对一查询、二级缓存、一对多查、WhenCase等复杂函数、Mapper功能、和拉姆达自定义扩展等,用好了是可以做到真正零SQL的一款ORM

首先将SqlSugar更新到4.8版本,下面我就来一一讲解每种查询的写法

创建DbContext

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DbContext
{
        public DbContext()
        {
            Db = new SqlSugarClient(new ConnectionConfig()
            {
                ConnectionString = "server=.;uid=sa;pwd=sasa;database=SqlSugar4XTest",
                DbType = DbType.SqlServer,
                IsAutoCloseConnection = true,//开启自动释放模式和EF原理一样我就不多解释了
                //InitKey默认SystemTable
            });
        }
        public SqlSugarClient Db;//用来处理事务多表查询和复杂的操作
        public SimpleClient<Student> StudentDb { get { return new SimpleClient<Student>(Db); } }//用来处理Student表的常用操作
        public SimpleClient<School> SchoolDb { get { return new SimpleClient<School>(Db); } }//用来处理School表的常用操作
}

单表的简单查询

我们使用的SimpleClient实现了简单的单表查询,如何扩展SimpleClient可以看我的上一篇文章

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 //调式代码 用来打印SQL  Db.Aop.OnLogExecuting = (sql, pars) => { Console.WriteLine(sql + "\r\n" + Db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value))); Console.WriteLine(); }; var data1 = StudentDb.GetById(1);//根据ID查询 var data2 = StudentDb.GetList();//查询所有 var data3 = StudentDb.GetList(it => it.Id == 1); //根据条件查询  var p = new PageModel() { PageIndex=1,PageSize=2};// 分页查询 var data4 = StudentDb.GetPageList(it => it.Name == "xx", p); Console.Write(p.PageCount);//返回总数 // 分页查询加排序 var data5 = StudentDb.GetPageList(it => it.Name == "xx", p,it=>it.Name,OrderByType.Asc); Console.Write(p.PageCount);//返回总数

对于Grid控件来说我一般用这个表单封装好了全部通用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 List<IConditionalModel> conModels = new List<IConditionalModel>(); conModels.Add(new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.Equal, FieldValue = "1" });//id=1 conModels.Add(new ConditionalModel() { FieldName = "Student.id", ConditionalType = ConditionalType.Equal, FieldValue = "1" });//id=1 conModels.Add(new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.Like, FieldValue = "1" });// id like '%1%' conModels.Add(new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.IsNullOrEmpty }); conModels.Add(new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = "1,2,3" }); conModels.Add(new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.NotIn, FieldValue = "1,2,3" }); conModels.Add(new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.NoEqual, FieldValue = "1,2,3" }); conModels.Add(new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.IsNot, FieldValue = null });// id is not null var data6 = StudentDb.GetPageList(conModels,p,it=>it.Name,OrderByType.Asc); //组装条件当查询条件的 分页查询加排序
简单查询中拉姆达的使用技巧

基本上和EF差不太多

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 var data3 = StudentDb.GetList(it => it.Name.Contains("a")); // like %a% 模糊查询 var p2 = new int[] { 1, 2, 3 }; var data31 = StudentDb.GetList(it => p2.Contains(it.Id)); // id in (1,2,3)

我们还支持了SqlFunc.xxx一串方法来给我们使用,如下用法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var data311 = StudentDb.GetList(it => SqlFunc.Between(it.Id,1,2)); // id between 1 and 2

动态拼表达式查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 var exp = Expressionable.Create<Student>() .OrIF(1 == 1, it => it.Id == 11) .And(it => it.Id == 1) .AndIF(2 == 2, it => it.Id == 1) .Or(it => it.Name == "a1").ToExpression();//拼接表达式 var data311 = StudentDb.GetList(exp); // 动态表达式查询

扩展拉姆达方法

例如我们有自定义的SQL函数或者SqlSugar不支持的我们可以自定扩展

具体看这个连接 http://www.codeisbug.com/Doc/8/1162

复杂查询

我们上面看到的简单查询底层都是用复杂查询实现的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var data1 = StudentDb.GetById(1); //等同于 var data2 = Db.Queryable<Student>().Single(it => it.Id == 1);

多表查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var list = Db.Queryable<Student, School>((st, sc) => new object[] { JoinType.Left,st.SchoolId==sc.Id}) .Select((st,sc)=>new{Id=st.Id,Name=st.Name,SchoolName=sc.Name}).ToList();

生成的SQL如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT [st].[ID] AS [id] , [st].[Name] AS [name] , [sc].[Name] AS [schoolName] FROM [STudent] st Left JOIN School sc ON ( [st].[SchoolId] =[sc].[Id])

多表查询自支持自动填充到ViewModel

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var s11 = Db.Queryable<Student, School>((st, sc) => st.SchoolId == sc.Id) .Select<ViewModelStudent3>().ToList();
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public class ViewModelStudent3: Student { public string SchoolName { get; set; } }

生成的Sql如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT sc.[Name] AS [SchoolName],--这一列神奇的自动出现了 sc.[Id] AS [scId], st.[ID] AS [Id], st.[SchoolId] AS [SchoolId], st.[Name] AS [Name], st.[CreateTime] AS [CreateTime] FROM [STudent] st ,[School] sc WHERE ( [st].[SchoolId] = [sc].[Id])

多表分页查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 var list3 = Db.Queryable<Student, School>((st, sc) => new object[] { JoinType.Left,st.SchoolId==sc.Id }).Select<ViewModel>() .ToPageList(pageIndex,pageSize)

子查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var getAll = Db.Queryable<Student, School>((st, sc) => new object[] { JoinType.Left,st.Id==sc.Id}) .Where(st => st.Id == SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Select(s => s.Id)) .ToList(); //生成的MYSQL语句,如果是SqlServer就是TOP 1 SELECT `st`.`ID`,`st`.`SchoolId`,`st`.`Name`,`st`.`CreateTime` FROM `STudent` st Left JOIN `School` sc ON ( `st`.`ID` = `sc`.`Id` ) WHERE ( `st`.`ID` =(SELECT `Id` FROM `School` WHERE ( `Id` = `st`.`ID` ) limit 0,1))

一对一的查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var getAll = Db.Queryable<Student, School>((st, sc) => new object[] { JoinType.Left,st.Id==sc.Id}) .Select(st => new{ name = st.Name, id = SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Select(s => s.Id) }).ToList();

本文只讲重点,更多多表查询请看 API

http://www.codeisbug.com/Doc/8/1124

Mapper功能

如果说 .Select() 也可以实现一对一的查询或者一些SQL函数但是毕竟是用来生成SQL的所以有很多局限性,Mapper是在查询出结果后进行处理所以任何C#方法都支持

也更强大

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 var s12 = db.Queryable<Student, School>((st, sc) => st.SchoolId == sc.Id).Select<ViewModelStudent3>() .Mapper(it => { it.Name = Md5(it.Name); //有多少列要处理写多少列,能用Mapper的就少用Select兼容性更好些 }).ToList();

高性能的一对多查询

我们也可以用Mapper来实现一对多,弥补.Select()不足

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var s12 = db.Queryable<Student, School>((st, sc) => st.SchoolId == sc.Id).Select<ViewModelStudent3>() .Mapper((it, cache) => { var allSchools = cache.GetListByPrimaryKeys<School>(vmodel => vmodel.SchoolId); //in(ViewModelStudent3[0].SchoolId , ViewModelStudent3[1].SchoolId...) /*one to many*/ it.Schools = allSchools.Where(i => i.Id == it.SchoolId).ToList(); /*C# syntax conversion*/ it.Name = it.Name == null ? "null" : it.Name; }).ToList();

一对多查询的性能可以秒杀其它ORM ,因为生成的SQL只有2条,并且这2条不会多查询一条没用的记录,有幸趣的可以研究一下,其它的都内存处理

多Queryable查询

Union all查询将结果集合并

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var getUnionAllList2 = db.UnionAll(db.Queryable<Student>(), db.Queryable<Student>()).ToList();//union all

两个Queryable联表查询(有人说我只支持12表JOIN,那这样就可以支持24张表了)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var q1 = db.Queryable<Student, School>((st,sc)=>new object[] { JoinType.Left,st.SchoolId==sc.Id }).Select((st, sc) => new ViewModelStudent4() { Id=st.Id, Name=st.Name,SchoolName=sc.Name }); var q2 = db.Queryable<School>(); var innerJoinList = db.Queryable(q1, q2, (j1, j2) => j1.Id == j2.Id).Select((j1, j2) => j1).ToList();//inner join var leftJoinList = db.Queryable(q1, q2,JoinType.Left, (j1, j2) => j1.Id == j2.Id).Select((j1, j2) => j1).ToList();/

二级缓存支持

二级缓存功能是对查询出来的数据进行缓存,在缓存不失效的情况下,下次同样的查询操作都会从缓存内读取

使用缓存查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var list=db.Queryable<Student, School>((s1, s2) => s1.Id == s2.Id).Select(s1 => s1).WithCache().ToList();//可以设置过期时间WithCache(60)

删除缓存

我们需要删除缓存也相当方便,只需要在对该表操作的时候加 RemoveDataCache 就能把查询中引用该表的缓存全部清除

db.Deleteable<Student>().Where(it => it.Id == 1).RemoveDataCache().ExecuteCommand();

//Updateable和Insertable一样用法

自动删除缓存

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = Config.ConnectionString, MoreSettings =new ConnMoreSettings(){ IsAutoRemoveDataCache=true }

创建db对象

我们需要创建一个MyCache类,你可以用我写好的也可以用你自已写的实现缓存

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ICacheService myCache = new RedisCache("10.1.249.196");//ICacheService SqlSugarClient db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = Config.ConnectionString, DbType = DbType.SqlServer, IsAutoCloseConnection = true, ConfigureExternalServices = new ConfigureExternalServices() { DataInfoCacheService = new RedisCache() //RedisCache是继承ICacheService自已实现的一个类 } }); 

我写好的Cache类可以作为参考

Redis:

https://github.com/sunkaixuan/SqlSugar/blob/dev/Src/Asp.Net/SqlSugar.Extensions.DataCache/RedisCache.cs

.Net自带Cache:

https://github.com/sunkaixuan/SqlSugar/blob/dev/Src/Asp.Net/SqlSugar.Extensions.DataCache/HttpRuntimeCache.cs

永久开源,源码下:

https://github.com/sunkaixuan/SqlSugar

SqlSugar一直在默默进步,得到了一些大型企业的认可,但这只是开始,希望你喜欢。

上一篇

https://www.cnblogs.com/sunkaixuan/p/8454844.html

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/168072.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
李兴华Java核心技术讲解--类集框架笔记
3.1、认识类集(理解) 如果现在要想保存多个对象,肯定使用对象数组完成,但是对象数组本身有一个最大的问题在于其数据的长度,所以后来使用了链表完成了动态对象数组的开发,可是链表的开发难度实在是很大,而且如果一个链表要想真正去使用,只依靠之前所编写的还不够,还需要进行一些代码的调优。 而在JDK 1.2之后正式引入了类集的概念,类集是一种动态的对象数组,属于各个数据结构的实现类,在整个类集之中主要的组成是一些核心的操作接口:Collection、List、Set、Map、Iterator、Enumeration。 3.2、单值保存的最大父接口:Collection(重点) 所谓的单值保存指的是每一次操作只会保存一个对象,就好像之前的链表程序一样,每一次只保存了一个对象,在Collection接口之中定义了如下的一些操作方法。 No. 方法名称 类型 描述 1 public boolean add(E e) 普通 数据增加 2 public void clear() 普通 清除数据 3 public boolean contains(Object o) 普通 查找数据是否存在 4 public boolean isEmpty() 普通 判断是否为空集合 5 public Iterator iterator() 普通 为Iterator接口实例化 6 public boolean remove(Object o) 普通 删除数据 7 public int size() 普通 取得集合的个数 8 public Object[] toArray() 普通 将集合变为对象数组 在Collection接口之中一共定义了15个方法,在所有的方法之中,只有两个方法最为常用:add()、iterator()。不过从开发上讲,很少会去直接使用Collection,都会使用Collection的两个子接口:List、Set。 3.3、允许重复的子接口:List(重点,80%) List是Collection的一个最为常用的子接口,首先这个接口的定义如下: public interface List extends Collection 但是List接口对Collection接口进行了大量的扩充,但是扩充之后的主要方法: No. 方法名称 类型 描述 1 public E get(int index) 普通 取得指定索引位置上的数据 2 public E set(int index, E element) 普通 修改指定索引位置上的数据 3 public ListIterator listIterator() 普通 为ListIterator接口实例化 但是以上的三个方法,只是针对于List接口起作用,而List接口有两个常用子类:ArrayList、Vector。 3.3.1、新的子类:ArrayList,95% ArrayList是List子接口使用最多的一个子类,而这个类的定义如下: public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, Serializable 按照面向对象的概念来讲,现在使用ArrayList主要的目的是为List接口实例化,所有的操作方法都以List接口为主。 范例:使用ArrayList进行List接口的功能验证 package cn.mldn.demo; import java.util.ArrayList; import java.util.List; public class TestDemo { public static void main(String[] args) throws Exception { List all = new ArrayList() ; all.add(“Hello”) ; all.add(“Hello”) ; // 内容重复了 all.add(“World”) ; for (int x = 0; x < all.size(); x++) { String str = all.get(x) ; // get()方法只有List接口有 System.out.print(str + “、”); } } } 在使用代码的时候可以发现,List集合之中即使存在了重复数据,也可以正常的保存,而且数据保存的顺序就是存入数据的顺序。 范例:使用List集合修改之前的程序 package cn.mldn.demo; import java.util.ArrayList; import java.util.List; interfac
葆宁
2019/04/18
6300
Java笔记(3)
三种通用的遍历方式: 迭代器:在遍历的过程中需要删除元素,请使用迭代器。 增强for、Lambda: 仅仅想遍历,那么使用增强for或Lambda表达式
用户11062199
2024/05/31
890
HashMap的知识回顾
fail-fast是集合世界中错误检测机制,通常出现在集合元素的遍历过程中, java.util包下所有的类都是fail-fast,而concurrent包中的集合都是fail-safe
在水一方
2022/06/14
2220
HashMap的知识回顾
java---集合(数据结构)(重点)
以前存储一组相同类型的数据使用数组,固定大小,具有连续性的存储空间。比如,5个长度的数组再存入数据时,如果现在已经存满,存入第六个元素,这时数组空间不够,扩容。Arrays.copyOf() , 很不方便,如果扩容频率太高,也影响你程序运行效率。集合来解决数组固定,如果扩容又影响效率的问题
用户10787181
2023/10/17
2530
java---集合(数据结构)(重点)
HashMap详解
**Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值。**这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
程序员阿杜
2023/08/25
2820
面试中最长常问到的 HashMap,你都知道多少?
推荐阅读:https://zhuanlan.zhihu.com/p/31610616
村雨遥
2020/08/13
3560
面试被问到HashMap 底层原理?看完这边文章绝对不慌!
存储:put 方法 put(key,value) 查询 : get 方法 get(key) java 代码如下
全栈程序员站长
2022/08/31
2790
Java开发知识之Java中的Map结构
  Map没有实现Collection接口,提供的是Key 到Value的映射. Map中.不能包含相同的Key,每个Key只能映射一个Value的值. 相当于就是 一一对应关系. 比如你有老婆,你是老公, 一个老公只能有一个老婆(在中国^_^),Kery还决定了存储对象在映射中的存储位置.但不是由Key对象本身决定的.而是一种散列技术进行处理.产生一个散列码的证书值.简单来说就是通过一串算法.算出的一个不会相同的值.
IBinary
2019/05/25
5920
java_Collection、Map、泛型的使用
集合按照其存储结构可以分为两大类,分别是 单列集合 java.util.Collection 双列集合 java.util.Map
咕咕星
2020/08/19
1.2K0
java_Collection、Map、泛型的使用
Java类集框架详细汇总
Java的类集框架比较多,也十分重要,在这里给出图解,可以理解为相应的继承关系,也可以当作重要知识点回顾;
BUG弄潮儿
2021/04/12
7220
这可能是最细的HashMap详解了!
# 手撕HashMap源码 > 文章已同步至GitHub开源项目: [Java超神之路](https://github.com/shaoxiongdu/java-notes) ### HashMap一直是面试的重点。今天我们来了解了解它的源码吧! > 首先看一下Map的继承结构图 ![image-20210906151448379](https://gitee.com/ShaoxiongDu/imageBed/raw/master/image-20210906151448379.png) > 源码
程序员阿杜
2021/09/11
2560
第十四届蓝桥杯集训——HashMap(无序)与TreeMap(有序)
HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。
红目香薰
2023/01/13
2240
第十四届蓝桥杯集训——HashMap(无序)与TreeMap(有序)
Java进阶-集合(2)
Map是一种键-值对(key-value)集合, 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象。用于保存具有映射关系的数据(Map是一种映射表,可以通过key快速查找value)。
reload
2024/02/28
1960
Java进阶-集合(2)
Java中的Map双边队列
键(Key)值(Value)对 邓超 = 娘娘 贝克汉姆 = 维多利亚 黄磊 = 孙莉 吴京 = 谢楠
用户7073689
2020/03/18
1.1K0
Java知识梳理 | 详析三大集合类(附实用例程 + 实践练习题)
1.3. 常用的集合有List集合、Set集合和Map集合;   List与Set继承了Collection接口,各接口还提供了不同的实现类。 常用集合类的继承关系如下:
凌川江雪
2019/01/28
1.3K0
JavaSE集合(八)之Map
前面给大家介绍了集合家族中的Collection家族,这一篇给大家分享的是集合中的另一个家族就是Map家族。以前的时候学习Map的时候没有很认真的去学习,我觉得很多东西还是不是很清楚。 这次我将总结的非常详细。程序员的道理里,我们风雨无阻! 一、Map接口 1.1、Map概述   Map 的字面翻译是映射(地图就是一种映射)。将键映射到值的对象,一个映射不能包含重复的键(如果有添加有重复的键,后面的会覆盖掉前面的,但是如果是自定义类型必须重写hashCode()和equals()方法),每个键最多只能映射到
用户1195962
2018/01/18
9660
JavaSE集合(八)之Map
Java——类集框架:Map集合的详解及应用举例(HashMap、Hashtable、TreeMap)
Map保存的是二元偶对象,简单说就是两个值,key和value。使用中可以通过key查找到value数据,使用Map可以方便用户查询。
Winter_world
2022/05/08
4210
Java——类集框架:Map集合的详解及应用举例(HashMap、Hashtable、TreeMap)
BAT面试必问HashMap源码分析
HashMap 主要用来存放键值对,它基于哈希表的Map接口实现,是常用的Java集合之一。
美的让人心动
2019/05/21
3210
BAT面试必问HashMap源码分析
JAVA知识回顾之Java8 Merge
putIfAbsent()是必要的,否则代码会在第一次出现未知的单词时中断,另外map.get(word) 里面map.put() 有点尴尬。
Jetpropelledsnake21
2022/09/29
3230
Map集合实例练习一
Map集合的特点,如是否可重复,是否有序仅作用在键上,如HashMap集合的键不得重复,值可以重复。
全栈程序员站长
2022/09/02
4300
相关推荐
李兴华Java核心技术讲解--类集框架笔记
更多 >
LV.0
腾讯
目录
  • 创建DbContext
  • 单表的简单查询
    • 简单查询中拉姆达的使用技巧
    • 动态拼表达式查询
    • 扩展拉姆达方法
  • 复杂查询
    • 多表查询
    • 多表查询自支持自动填充到ViewModel
  • Mapper功能
    • 高性能的一对多查询
  • 多Queryable查询
  • 二级缓存支持
    • 使用缓存查询
    • 删除缓存
    • 自动删除缓存
    • 创建db对象
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档