喜欢 Dapper 的朋友看过来,送一份厚礼
写在开头
众所周知 Dapper 是 .NET 下最轻最快的 ORM,它是喜欢写 SQL 码农的福音,相对于 SqlHelper 它更加方便,据统计 10个 .NETer 有 9个 用过 Dapper。
由于 .NET 环境的特殊,对 Lambda 表达式树的喜爱,于是市面上有很多出现了基于 Dapper 的轻量级 ORM,它们几乎都有共同特点,让 Dapper 支持 Lambda 表达式树,写起来顺畅如流水。
今天介绍一款本身功能已经很强大的 ORM,他提供一个隐藏得比较深的 API 功能,使用起来和 Dapper 没什么两样。
了解 Lambda 表达式树
这要先从 Lambda 表达式开始说起,词语中少了一个“树”字,差别甚大。
表达式,如下各种语法糖骚操作,产生的 IL 一模一样:
//使用C# 2.0中的匿名方法获取字符串长度
Func<string, int> strLength = delegate(string str) { return str.Length; };
Console.WriteLine(strLength("Hello World!"));
//使用Lambda表达式
//(显式类型参数列表)=> {语句},lambda表达式最冗长版本
strLength = (string str) => { return str.Length; };
Console.WriteLine(strLength("Hello World!"));
//单一表达式作为主体
//(显式类型参数列表)=> 表达式
strLength = (string str) => str.Length;
Console.WriteLine(strLength("Hello World!"));
//隐式类型的参数列表
//(隐式类型参数列表)=> 表达式
strLength = (str) => str.Length;
Console.WriteLine(strLength("Hello World!"));
//单一参数的快捷语法
//参数名 => 表达式
strLength = str => str.Length;
Console.WriteLine(strLength("Hello World!"));
而表达式树呢,代码写起来跟表达式差不多,如下:
Expression<Func<string, int>> strLength = str => str.Length;
表达式树不支持代码块(花括号)
力求书写简单,一般情况我们都是这样写的,虽然它和表达式代码写起来几乎一样,但是返回值和表达式不一样,多了一个泛型 Expression<>。
表达式树也称表达式目录树,将代码以一种抽象的方式表示成一个对象树,树中每个节点本身都是一个表达式。表达式树不是可执行代码,它是一种数据结构。它是代码在编译期间将编写的代码转换成一个树结构,以便后续进行逆向解析。
如上:(strLength.Body as MemberExpression).Member.Name 可以得到值 "Length"
由于表达式树可逆向解析的特点,近十年来 EF 是一直是带头大哥,国产每年都要整出好几个 ORM,大部分都是基于表达式树解析做的。
表达式树解析
.NET 技术文章从来不缺少表达式树解析的这类文章,有兴趣的可以百度搜索一下,很多很多,但是想做完美可不是件简单事。
FreeSql 在表达式树解析上做了下足了工夫,举例:
1、子表 in 查询
.Where(a => fsql.Select<T>().ToList(b => b.Id).Contains(a.Id))
//WHERE a.Id in (select id from t)
2、子表 exists 查询
.Where(a => fsql.Select<T>().Any(b => b.Id == a.Id))
//WHERE exists(select 1 from t where Id = a.Id)
3、日期格式化
ToList(a => a.CreateTime.ToString("HH:mm:ss")
//date_format(a.`CreateTime`, '%H:%i:%s')
4、开窗函数
ToList(a => SqlExt.Rank().Over().OrderBy(a.Id).OrderByDescending(b.EdiId).ToValue())
//rank() over(order by a.Id, b.EdiId desc)
5、Join 子表
ToList(a => string.Join(",", fsql.Select<StringJoin01>().ToList(b => b.Id)))
//(SELECT group_concat(b.`Id` separator ',') FROM `StringJoin01` b)
这些特性在不同的数据库,都需要做相应适配实现,FreeSql 还支持对导航属性的表达式树解析,说这些只想证明做到细致真的不容易。
与其自己造着麻烦,不如直接拿来主义使用?
Ado.Net 扩展实现
与其自己造着麻烦,不如直接拿来主义使用?FreeSql 提供了一种非主打的 API 使用习惯,使用起来跟 Dapper 没什么区别。
支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/神通/人大金仓/翰高/MsAccess 十多种数据库适配,并且支持 .NetFramework 4.0 平台、.NET5.0、.NET Core2.1 + 平台。
第一步:以数据库 SqlServer 访问为例,只需要安装已经划分好的小包:
dotnet add packages FreeSql.Provider.SqlServer
or
Install-Package FreeSql.Provider.SqlServer
第二步:建立实体类
class TestConnectionExt {
public Guid id { get; set; }
public string title { get; set; }
public DateTime createTime { get; set; } = DateTime.Now;
}
第三步:开始 CRUD
using (var conn = new SqlConnection(connectString)) {
var list = conn.Select<TestConnectionExt>().Where(a => a.id == item.id).ToList();
}
using (var conn = new SqlConnection(connectString)) {
var item = new TestConnectionExt { title = "testinsert" };
var affrows = conn.Insert(item).ExecuteAffrows();
}
using (var conn = new SqlConnection(connectString)) {
var affrows = conn.Update<TestConnectionExt>()
.Where(a => a.Id == xxx)
.Set(a => a.title, "testupdated")
.ExecuteAffrows();
}
using (var conn = new SqlConnection(connectString)) {
var affrows = conn.Delete<TestConnectionExt>()
.Where(a => a.Id == xxx)
.ExecuteAffrows();
}
添加或更新:
using (var conn = new SqlConnection(connectString)) {
var affrows = conn.InsertOrUpdate<TestConnectionExt>()
.SetSource(item)
.ExecuteAffrows();
}
如上添加、删除、修改、查询,已经支持实体类操作,并且支持批量插入、批量更新、批量删除、多表查询、导航属性查询。
可以享用 FreeSql 几乎所有功能。
结束语
FreeSql 使用世界上最宽松的开源协议 MIT 托管于 github:https://github.com/dotnetcore/FreeSql 目前已发布经历两年高频率迭代的稳定版本 v2.0,欢迎关注和使用。
支持 .NetFramework 4.0+、.NetCore 2.1+、Xamarin 等支持 NetStandard 所有运行平台。
支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/神通/人大金仓/翰高/MsAccess 数据库。
QQ群:4336577(已满)、8578575(在线)、52508226(在线)
喜欢 Dapper 的朋友看过来,送一份厚礼的更多相关文章
- 在Centos上面用yum不能安装redis的朋友看过来
我得是centos 6.3,如果直接用yum安装redis,报错,如下:[root@CentOS6 etc]# yum install redisLoaded plugins: fastestmirr ...
- PS2手柄在arduino上进行测试,可用,供喜欢diy的朋友借鉴
#include <PS2X_lib.h> //PS2手柄PS2X ps2x; // create PS2 Controller Class//////////PS2引脚///////// ...
- 5年后,我们为什么要从 Entity Framework 转到 Dapper 工具?
前言 时间退回到 2009-09-26,为了演示开源项目 FineUI 的使用方法,我们发布了 AppBox(通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块),最初的 ...
- 如何将 Dapper 换成 SqlSuagr ORM
为什么要写这篇文章 因数我看到很多人虽然用着SqlSugar,但是同时也用着Dapper,因为SqlSugar兼容了Dapper所有API,所以既然你用了SqlSugar那么就没有必要在同一个项目中使 ...
- 使用轻量级ORM Dapper进行增删改查
项目背景 前一段时间,开始做一个项目,在考虑数据访问层是考虑技术选型,考虑过原始的ADO.NET.微软的EF.NH等.再跟经理讨论后,经理强调不要用Ef,NH做ORM,后期的sql优化不好做,公司 ...
- 为什么喜欢Kindle
为什么喜欢Kindle 有朋友问为什么那么多人喜欢用Kindle,作为刚入手一台Kindle PaperWhite 2 的人, 我想说:这个东西,应该算今年我买的最值得的设备了.它的好处太多了:1:轻 ...
- 从HTML Components的衰落看Web Components的危机 HTML Components的一些特性 JavaScript什么叫端到端组件 自己对Polymer的意见
http://blog.jobbole.com/77837/ 原文出处: 徐飞(@民工精髓V) 搞前端时间比较长的同学都会知道一个东西,那就是HTC(HTML Components),这个东西名字很现 ...
- Dapper进行增删改查 z
http://www.cnblogs.com/huangkaiyan10/p/4640548.html 项目背景 前一段时间,开始做一个项目,在考虑数据访问层是考虑技术选型,考虑过原始的ADO.NET ...
- python高级—— 从趟过的坑中聊聊爬虫、反爬以及、反反爬,附送一套高级爬虫试题
前言: 时隔数月,我终于又更新博客了,然而,在这期间的粉丝数也就跟着我停更博客而涨停了,唉 是的,我改了博客名,不知道为什么要改,就感觉现在这个名字看起来要洋气一点. 那么最近到底咋不更新博客了呢?说 ...
随机推荐
- 要求用户输入用户名和密码,只要不是admin、888888就
要求用户输入用户名和密码,只要不是admin.888888就一直提示用户名或密码错误,请重新输入 Console.WriteLine("输入账号和密码"); string a = ...
- LDA与PCA
参考: https://www.cnblogs.com/pinard/p/6244265.html https://blog.csdn.net/qq_25680531/article/details/ ...
- STM32最小系统板OLED贪吃蛇
上次用STM32F103最小系统板做了一个简单的OLED贪吃蛇小游戏,以下为游戏效果动图: 主要实现内容包括:贪吃蛇移动.方向控制.食物生成.分数处理.死亡判定. 这次想把自己的制作思路分享给大家,不 ...
- Flask补充内容
关键字: 一,过滤器 二,增删改查 一,过滤器 1,概念:过滤器的本质就是函数.有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化.运算等等,而在模板中是不能直接调用 Pyth ...
- 认识Javascript中的作用域和作用域链
作用域 只要写过java或者c#等语言的同学来说,相信一定能理解作用域的概念,在作用域的范围中,我们可以使用这个作用域的变量,对这个变量进行各种操作.可是,当使用Javascript的时候,相信很多的 ...
- [leetcode/lintcode 题解] 微软 面试题:实现 Trie(前缀树)
实现一个 Trie,包含 insert, search, 和 startsWith 这三个方法. 在线评测地址:领扣题库官网 样例 1: 输入: insert(" ...
- leetcode 30day--2
202. Happy Number Write an algorithm to determine if a number n is "happy". A happy number ...
- Loadrunner学习(一)
一个优秀的软件系统不单单具有良好的功能,还需要有过硬的性能,一个只通过功能测试的系统,只能称之为"可用",而不能算是"好用".当然,性能测试需要基于功能测试,只 ...
- Jar 和 war 区别
jar包:对于学习java的人来说应该并不陌生.我们也经常使用也一些jar包.其实jar包就是java的类进行编译生成的class文件就行打包的压缩包而已.里面就是一些class文件.当我们自己使用m ...
- python学习-pickle模块(序列化)
简介 1 python-pickle模块 该pickle模块实现了用于序列化和反序列化Python对象结构的二进制协议. "Pickling"是将Python对象层次结构转换为字节 ...