与 Dapper 比较

众所周知 Dapper 是 .NET 下最轻最快的 ORM,它是喜欢写 SQL 码农的福音,相对于 SqlHelper 它更加方便,据统计 10个 .NETer 有 9个 用过 Dapper。

这篇文章为准备使用 FreeSql 的朋友解惑,对比 Dapper 有何优势,为什么要使用 FreeSql?希望本文内容对大家有所帮助。

关于性能(输了)

Dapper + SQL 是大家一般所用的方式,性能对比主要体现在两个阶段:

1、执行前,表达式树解析,拼接 SQL 的消耗:

  • Dapper 几乎没有消耗;
  • FreeSql 会存在递归解析、对象拆箱等操作;

从项目工程可维护性角度看,这一点性能损失是能被容忍的,请看下面的测试结果。

2、执行后,返回数据转换为 List:

  • Dapper 采用 Emit 构造委托并缓存,性能接近原生代码;
  • FreeSql 采用 ExpressionTree 构造委托并缓存,为了映射类型更加易用使用了一点装箱操作,性能比 Dapper 略低;
Method size Mean Error StdDev Median Rank
FreeSqlSelect 1 512.1 us 25.99 us 75.82 us 519.6 us 3
SqlSugarSelect 1 438.6 us 27.87 us 81.75 us 428.1 us 2
EfCoreSelect 1 594.3 us 36.51 us 107.08 us 593.9 us 4
DapperSelete 1 287.5 us 22.10 us 63.77 us 281.7 us 1
FreeSqlSelect 500 1,022.0 us 72.17 us 212.79 us 957.0 us 6
SqlSugarSelect 500 1,338.1 us 90.51 us 261.15 us 1,311.5 us 7
EfCoreSelect 500 1,390.0 us 101.53 us 296.18 us 1,319.8 us 7
DapperSelete 500 919.0 us 48.37 us 139.55 us 891.0 us 5

如上测试 Top1、Top500 单表查询水平结果

测试注意 IFreeSql 是单例模式设计,请勿重复创建,测试前请预热

测试结果是 us 级别的慢,能接受,因为数据库的上限并发瓶颈比较低(几万的水平),应用程序中的这一点消耗远不是问题。

最怕方法或设计错了导致的慢,那慢就是秒级以上的慢了,无力回天。

关于功能(赢了)

Dapper 几乎只有执行 SQL 的功能,市面上有一些基于 Dapper 做的轻量级 ORM,可以对实体对象进行 CRUD 操作,支持的数据库有限。

Dapper 在功能方面几乎完败于 FreeSql,例如:

  • CodeFirst:Dapper 不支持;
  • 类型映射:Dapper 在不同数据库之间的类型映射容易报错。比如实体类属性是 string,但是数据库类型是 int,非常容易报错,这不是杠,真实项目中有很多非等映射类型存在;
  • 表达式树:Dapper 不支持导航属性、自定义解析、以及特别的解析;
  • 导航属性:Dapper 不支持;
  • 批量插入:Dapper 需要自己写 SQL 或者引入第三方包,FreeSql 自带集成;
  • 批量更新:Dapper 需要自己写 SQL,FreeSql 自带集成;
  • 工作单元:Dapper 需要引入第三方包,FreeSql 自带集成;
  • 读写分离:??
  • 全局过滤:??

等等。。。

FreeSql 赢在功能丰富,给使用者提供最大便利,你准备好入坑了吗?

如何接入(老项目)

如果你的项目正在使用 Dapper,请看以下成本最低的接入方法。

FreeSql 支持调用 SQL/存储过程,同时也为 IDbConnection/IDbTransaction 提供扩展方法 Select/Delete/Insert/Update/InsertOrUpdate。

第一步:以数据库 SqlServer 访问为例,只需要安装已经划分好的小包:

  1. dotnet add packages FreeSql.Provider.SqlServer

or

  1. Install-Package FreeSql.Provider.SqlServer

第二步:建立实体类

  1. class TestConnectionExt {
  2. public Guid id { get; set; }
  3. public string title { get; set; }
  4. public DateTime createTime { get; set; } = DateTime.Now;
  5. }

第三步:开始 CRUD

  1. using (var conn = new SqlConnection(connectString)) {
  2. var list = conn.Select<TestConnectionExt>().Where(a => a.id == item.id).ToList();
  3. }
  4. using (var conn = new SqlConnection(connectString)) {
  5. var item = new TestConnectionExt { title = "testinsert" };
  6. var affrows = conn.Insert(item).ExecuteAffrows();
  7. }
  8. using (var conn = new SqlConnection(connectString)) {
  9. var affrows = conn.Update<TestConnectionExt>()
  10. .Where(a => a.Id == xxx)
  11. .Set(a => a.title, "testupdated")
  12. .ExecuteAffrows();
  13. }
  14. using (var conn = new SqlConnection(connectString)) {
  15. var affrows = conn.Delete<TestConnectionExt>()
  16. .Where(a => a.Id == xxx)
  17. .ExecuteAffrows();
  18. }

添加或更新:

  1. using (var conn = new SqlConnection(connectString)) {
  2. var affrows = conn.InsertOrUpdate<TestConnectionExt>()
  3. .SetSource(item)
  4. .ExecuteAffrows();
  5. }

如上添加、删除、修改、查询,已经支持实体类操作,并且支持批量插入、批量更新、批量删除、多表查询、导航属性查询。

可以享用 FreeSql 几乎所有功能。

思考:使用这种 API 貌似可以很轻松的接入到 abp vnext 中?

学习指南

FreeSql 是一款功能强大的对象关系映射(O/RM)组件,支持 .NET Core 2.1+、.NET Framework 4.0+ 以及 Xamarin。

  • 🛠 支持 CodeFirst 模式,即便使用 Access 数据库也支持数据迁移;
  • 💻 支持 DbFirst 模式,支持从数据库导入实体类,或使用实体类生成工具生成实体类;
  • ⛳ 支持 深入的类型映射,比如 PgSql 的数组类型等;
  • ✒ 支持 丰富的表达式函数,以及灵活的自定义解析;
  • 🏁 支持 导航属性一对多、多对多贪婪加载,以及延时加载;
  • 📃 支持 读写分离、分表分库、过滤器、乐观锁、悲观锁;
  • 🌳 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/Access 等数据库;

基础

进阶

高级