各种ORM框架对比

目前框架有以下

  1. PetaPoco
  2. Dapper.NET
  3. Massive
  4. Simple.Data
  5. Chain

PetaPoco

轻量级,以前单文件,目前有维护形成项目级别,适合多个数据库,开发入手比较快,二次开发扩展简单,模型Emit映射,数据交互需要Code,并且需要编写脚本,接口上有自动翻页,支持多对象查询返回

使用示例:

//保存对象
db.Save(article);
db.Save(new Article { Title = "Super easy to use PetaPoco" });
db.Save("Articles", "Id", { Title = "Super easy to use PetaPoco", Id = Guid.New() }); //获取一个对象
var article = db.Single<Article>();
var article = db.Single<Article>("WHERE ArticleKey = @0", "ART-123"); //删除一个对象
db.Delete(article);
db.Delete<Article>();
db.Delete("Articles", "Id", );
db.Delete("Articles", "ArticleKey", "ART-123");

Dapper.NET

轻量级,单文件,支持多数据库,模型Emit反射,数据交互需要Code,开发入手也比较快,二次开发扩展简单,支持多对象查询返回,优势在于写入数据比PetaPoco更加灵活,但编码性工作要求会更多

使用示例:

注意:所有扩展方法假定连接已打开,如果连接关闭,它们将失败

//IDbConnection扩展查询
public static IEnumerable < T > Query < T >(this IDbConnection conn,string sql,object param = null,SqlTransaction transaction = null,bool buffered = true)
  • 单个查询:
public class Dog
{
public int? Age { get; set; }
public Guid Id { get; set; }
public string Name { get; set; }
public float? Weight { get; set; } public int IgnoredProperty { get { return ; } }
}
//简单查询
var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
//验证统计数量
dog.Count()
.IsEqualTo();
//验证属性是否为null
dog.First().Age
.IsNull();
//验证属性是否匹配
dog.First().Id
.IsEqualTo(guid);
  • 多个查询,并且返回一个动态列表:


//查询两行数据
var rows = connection.Query("select 1 A, 2 B union all select 3, 4");
//行一数据
((int)rows[].A)
.IsEqualTo();
((int)rows[].B)
.IsEqualTo();
//行二数据
((int)rows[].A)
.IsEqualTo();
((int)rows[].B)
.IsEqualTo();
 
  • IDbConnection扩展执行
public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)
  • 执行一个插入操作
connection.Execute(@"
set nocount on
create table #t(i int)
set nocount off
insert #t
select @a a union all select @b
set nocount on
drop table #t", new {a=, b= })
.IsEqualTo();
  • 同一张表插入多个数据

注意:如果是大批量插入不建议这么使用,请用ADO.NET自带的BatchInsert

connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
new[] { new { a=, b= }, new { a=, b= }, new { a=, b= } }
).IsEqualTo();

Massive

非单文件,但也是轻量级,项目在持续维护,支持多数据库,和dapper和PetaPoco运用有点截然不同;它是用类对象继承DynamicModel来模拟实体对象的查询和写入,似乎没有看到多对象多表联合查询和返回,局限性还是比较小

代码示例

public class Products:DynamicModel {
public Products():base("northwind", "products","productid") {}
}
var table = new Products();
var products = table.All();
//获取查询字段和搜索条件
var productsFour = table.All(columns: "ProductName as Name", where: "WHERE categoryID=@0",args: );
//分页查询
var result = tbl.Paged(where: "UnitPrice > 20", currentPage:, pageSize: );
var poopy = new {ProductName = "Chicken Fingers"};
//更新 Product对象到表, 条件 ProductID = 12 ,设置 ProductName of "Chicken Fingers"
table.Update(poopy, ) //插入数据
var table = new Categories();
var inserted = table.Insert(new {CategoryName = "Buck Fify Stuff", Description = "Things I like"});
//插入成功后得到返回新对象
var newID = inserted.CategoryID;

Simple.Data

  • ADO-based access to relational databases, with providers for:

    • SQL Server 2005 and later (including SQL Azure)
    • SQL Server Compact Edition 4.0
    • Oracle
    • MySQL 4.0 and later
    • SQLite
    • PostgreSQL
    • SQLAnywhere
    • Informix
  • MongoDB
  • OData

项目已经比较老,目前已经4-5年未更新代码,里面类文件比较多,算不上轻量级,运用上比较简单

以下是代码截图


Chain

一种基于函数式编程理念的Fluent ORM,项目今年少有更新,运用上几乎不写脚本,类似EF的数据对应模型开发,和我们常规面向对象开发有点差异,我对它的获知来源也是在InfoQ上得知,

地址:http://www.infoq.com/cn/articles/repository-implementation-strategies?utm_source=articles_about_dotnet&utm_medium=link&utm_campaign=dotnet

//插入数据
public int Insert(Employee employee)
{
return m_DataSource.Insert("HR.Employee", employee).ToInt32().Execute();
} //更新数据
public void Update(Employee employee)
{
m_DataSource.Update("HR.Employee", employee).Execute();
} //初学者更新实体(但容易出问题,如果对应的漏写了一个属性的赋值)
public void Update(Employee employee)
{
using (var context = new CodeFirstModels())
{
var entity = context.Employees.Where(e => e.EmployeeKey == employee.EmployeeKey).First();
entity.CellPhone = employee.CellPhone;
entity.FirstName = employee.FirstName;
entity.LastName = employee.LastName;
entity.ManagerKey = employee.ManagerKey;
entity.MiddleName = employee.MiddleName;
entity.OfficePhone = employee.OfficePhone;
entity.Title = employee.Title;
context.SaveChanges();
}
} //中级者更新
public void Update(Employee employee)
{
using (var context = new CodeFirstModels())
{
context.Entry(employee).State = EntityState.Modified;
context.SaveChanges();
}
} //获取指定表全部数据
public IList<Employee> GetAll()
{
return m_DataSource.From("HR.Employee").ToCollection<Employee>().Execute();
}

压测截图

这个压测图是截图Dapper官方代码库里的,估计有点老,下面评论的朋友也纠正了这点,谢谢,所有先忽略这个EF的压测参考,等我实际压测后,会具体分享出优缺点

在博客园里发现这篇软文对EF VS Dapper 的测试:http://www.cnblogs.com/so9527/p/5674498.html#!comments ,那其实我也不用测试压力差距,唯一告诉我们EF也有自身的优势,微软这个产品迭代这么久的版本肯定一直在提升自己,如果有兴趣可以关注 Core 版本的性能,据说很快;如果熟悉DDD构架模式也知道利用EF这两者也是相当的默契度

由于网友:我是so 的要求,我也简单测试一下他的产品,代码如下,就只考虑单线程

       

Console.WriteLine($"开始Chloe测试");
using (MsSqlContext msSqlContext = new MsSqlContext("server=(local);user id=test;password=test;database=TestDb;"))
{
IQuery<Order> query = msSqlContext.Query<Order>();
//预热,因为我没去查阅你的源码,默认考虑预热
query.FirstOrDefault();
Stopwatch stopwatch = Stopwatch.StartNew();
IList<long> tmsList = new List<long>();
for (int i = 0; i < 10; i++)
{
stopwatch.Restart();
var data = query.ToList();
stopwatch.Stop();
var tms = stopwatch.ElapsedMilliseconds;
tmsList.Add(tms);
Console.WriteLine($"耗时:{tms}");
}
Console.WriteLine($"平均:{tmsList.Average()}");
Console.ReadKey();
}


Console.WriteLine($"开始Dapper测试");
using (IDbConnection connection = new SqlConnection("server=(local);user id=test;password=test;database=TestDb;"))
{
//也进行预热
connection.QueryFirst("SELECT TOP 1 OrderId,OrderNo FROM [Order]");
Stopwatch stopwatch = Stopwatch.StartNew();
IList<long> tmsList = new List<long>();
for (int i = 0; i < 10; i++)
{
stopwatch.Restart();
var data = connection.Query<Order>("SELECT OrderId,OrderNo FROM [Order]"); ;
stopwatch.Stop();
var tms = stopwatch.ElapsedMilliseconds;
tmsList.Add(tms);
Console.WriteLine($"耗时:{tms}");
}
Console.WriteLine($"平均:{tmsList.Average()}");
Console.ReadKey();
}


100万数据读取,模型包含两个字段,在DEBUG模式下单线程测试,单位:毫秒,由于每个人机器配置不同仅供参考

测试最终结果:


最后分析对比表,如果有异议,欢迎纠正

ORM框架 难易度 开源 轻量级度 性能 扩展性 项目切入
PetaPoco 容易 方便 麻烦点(非T4)
Dapper 容易 方便 麻烦点
Massive 还行 有点繁琐
Simple.Data 容易 足够用 快速
Chain 容易 还可以 足够用 快速
EF 容易 还可以 足够用 快速

纠正一下表格,把编码级改成项目切入更合适....

这篇对比文章的产生主要是我们公司的开发框架体系在做调整,需要基础框架来逐步切入到各个项目中,顺便也调研了这些轻量级ORM,到时进行权衡对比后再此基础上二次可能开发一个自己ORM,会考虑后期的读写库分离并且分布式措施,内部集成短期数据缓存机制等功能。

各种ORM框架对比(理论篇,欢迎来观摩,并且纠正部分错误,防止误区)的更多相关文章

  1. 各种ORM框架对比(理论篇,欢迎来观摩)

    各种ORM框架对比 目前框架有以下 PetaPoco Dapper.NET Massive Simple.Data Chain PetaPoco 轻量级,以前单文件,目前有维护形成项目级别,适合多个数 ...

  2. 手撸ORM浅谈ORM框架之基础篇

    好奇害死猫 一直觉得ORM框架好用.功能强大集众多优点于一身,当然ORM并非完美无缺,任何事物优缺点并存!我曾一度认为以为使用了ORM框架根本不需要关注Sql语句如何执行的,更不用关心优化的问题!!! ...

  3. 手撸ORM浅谈ORM框架之Add篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  4. 手撸ORM浅谈ORM框架之Update篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  5. 手撸ORM浅谈ORM框架之Delete篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  6. 手撸ORM浅谈ORM框架之Query篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  7. ORM框架对比以及Mybatis配置文件详解

    ORM框架对比以及Mybatis配置文件详解 0.数据库操作框架的历程 (1) JDBC ​ JDBC(Java Data Base Connection,java数据库连接)是一种用于执行SQL语句 ...

  8. .Net 常用ORM框架对比:EF Core、FreeSql、SqlSuger

    前言: 最近由于工作需要,需要选用一种ORM框架,也因此对EF Core.FreeSql.SqlSuger作简单对比.个人认为各有有优势,存在即合理,不然早就被淘汰了是吧,所以如何选择因人而议.因项目 ...

  9. Net环境下比较流行的ORM框架对比

    个人感觉在Java领域大型开发都离不了ORM的身影,所谓的SSH就是Spring+Struts+Hibernate,除了在学习基础知识的时候被告知可以使用JDBC操作数据库之外,大量的书籍中都是讲述使 ...

随机推荐

  1. Android单独继承View类来实现自定义控件

    一个单独继承view类来实现自定义控件,在该方法中,需要重写ondraw方法来绘制自己所需要的控件,下面也以一个简单的例子来说明如何实现自定义控件.该方法可以实现所需要的所有的自定义控件. 属性文件中 ...

  2. KendoUI Grid Pager部分 Nan-Nan of x Items

    相关问题: http://stackoverflow.com/questions/23941065/pager-error-in-kendo-gridnan-nan-of-1-items http:/ ...

  3. css广告弹窗满屏跑

    window.onload=function(){ //广告滚动 var oneInner = $('#divid')[0]; //定时器 var a1a = setInterval(moves,10 ...

  4. leetcode_41. First Missing Positive_cyclic swapping

    https://leetcode.com/problems/first-missing-positive/ 给定一个长度为len的无序数组nums,找到其第一个丢失的正整数. 解法: 使用cyclic ...

  5. 在Eclipse中设置自动补全

    在Eclipse中菜单中,Window->Preferences->Java->Editor->Content Assist中的Auto activation triggers ...

  6. OPENCV3 命名空间等变化

    CV_VERSION 表示的opencv的版本号 命名空间变化:  可以通过增加 #include <cv.h> 解决 1 直接去掉CV_ 前缀 1) nameWindow 函数    C ...

  7. linux 安装nginx 集成emq

    1:下载nginx-1.12.2.tar.gz http://nginx.org/en/download.html 2:解压 tar -zxvf  nginx-1.12.2.tar.gz 3:进行co ...

  8. LInux设备驱动分析—— kmalloc和kzalloc函数

    今晚在研究EVM5728开发板上面Linux系统的IIC设备驱动程序,偶然之间看到驱动程序中有一处使用了kzalloc函数,本人之前都是使用Linux内核提供的kmalloc / kfree函数来给设 ...

  9. ssh服务使用介绍二

    老司机开车了 快上车 上文提到当我们使用ssh远程链接主机的时候,会出现询问的提示,如果我们链接的机器多了,一遍一遍的输入是不是很麻烦?怎么解决如下 vim /etc/ssh/ssh_config 如 ...

  10. CSRF verification failed. Request aborted. 表单提交方法为POST时的报错

    本人所用Django版本为1.11,在设置请求方法为POST时,遇到标题中的错误,尝试了多种方法,最终通过下面的操作来修复: 在template文件中添加图中红框部分 接着,导入csrf_exempt ...