DapperPoco -- 基于Dapper的、轻量级的、高性能的、简单的、灵活的ORM框架
为什么要重复造轮子
因为现有的轮子都在某些方面不太令我满意,下面我来一一点评一下,欢迎拍砖。
Entity Framework
我喜欢傻瓜化使用方式的框架,同时又不失灵活性。
EF虽然使用起来足够简单,但却不够灵活。例如,在EF Core中你无法用原生SQL写一个多表连接查询(返回的结果是多表连接的结果)
单表简单条件查询还好,多表查询时生成的SQL性能实在不敢恭维,我更喜欢自己写SQL,可控性更高,心里有底
EF的设计不利于项目的分层;我理想的设计是隔离、低耦合,和数据库打交道的事就交给Db层好了,所有数据库的特性都隔离在Db层内部,对外按业务提供傻瓜化的接口。
而使用EF你没法做到真正的隔离,因为即使能把SaveChanges封装在Db层,导航属性也会导致再次查询数据库。
Dapper
我喜欢它的轻量级,高性能。但它"只支持"原生SQL读写数据库,使用起来还是不太方便。
很多常用的情景其实可以封装一下不用写SQL的,像EF一样,直接Add一个Entity
虽然现在Dapper已经有了这样一个封装,但目前来看实在过于粗糙
PetaPoco
它可以像EF一样直接Add一个Entity,也可以像Dapper一样自己写原生SQL,按理说这已经很完美了。
但是,它不支持批量插入、更新啊
DapperPoco
在实在找不到满意框架的情况下,于是DapperPoco就诞生了,它是基于Dapper高度封装的,有Dapper的一切优点,同时也弥补了它的不足,它有如下特点:
- 高性能(与Dapper一致),以热启动后计算(第一次启动有缓存过程)
- 像EF一样使用简单,也可像Dapper一样灵活使用原生SQL
- 支持使用Fluent API定义实体映射
- 内部模块化灵活、可扩展
现已将其开源并放到了github上,地址为:https://github.com/md-frank/DapperPoco
如何使用
首先定义一个Poco类
//表示文章表里的一条记录
public class Article
{
public long Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
创建DbContext
class MasterDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseConnectionString("连接字符串");
//使用SQL Server数据库
optionsBuilder.UseSqlAdapter(new SqlServerAdapter(SqlClientFactory.Instance));
} //如果不使用Poco可以不重写此方法
protected override void OnEntitiesBuilding(EntitiesBuilder entityBuilder)
{
//属性名与表列名(列名)不一样,可在此映射别名
entityBuilder.Entity<Article>()
.TableName("T_Article")
.ColumnName(p => p.Id, "article_id");
}
}
插入数据
var masterDb = new MasterDbContext(); //插入一个Poco对象
var a = new Article
{
Title = "hello",
Content = "hello word"
};
masterDb.Insert(a); //插入了2条记录
masterDb.Insert(new Article[] { a, a }); //也可以显式指定表名
masterDb.Insert(a, "T_Article"); //原生SQL插入
this.Execute("insert T_Article(Title, Content) values (@Title, @Content)", a); //插入了2条记录
this.Execute("insert T_Article(Title, Content) values (@Title, @Content)", a, a); //插入了2条记录
this.Execute("insert T_Article(Title, Content) values (@Title, @Content)", new Article[] { a, a }); //也可以直接写参数值
this.Execute("insert T_Article(Title, Content) values (@p0, @p1)", "hello", "hello word");
更新数据
var masterDb = new MasterDbContext(); //先查出来准备更新
var article = masterDb.FirstOrDefault<Article>("select * from T_Article where article_id = @p0", ); //更新除主键外的所有列
article.Title = "hello 2";
article.Content = "content 1";
masterDb.Update(article); //仅更新指定列,指定表列名
article.Title = "hello 2";
masterDb.Update(article, new [] { "Title" }); //仅更新指定列,指定实体属性名
article.Title = "hello 3";
article.Content = "content 1";
masterDb.Update(article, null, null, p=> p.Title, p=> p.Content);
保存数据
var masterDb = new MasterDbContext(); var article = new Article
{
Id = ,
Title = "hello",
Content = "hello word"
}; //如果记录存在则更新,不存在则插入
masterDb.Save(article); //保存并指定列名
masterDb.Save(article, new [] { "Title" });
删除数据
var masterDb = new MasterDbContext();
var article = masterDb.FirstOrDefault<Article>("select * from T_Article where article_id = @p0", );
//删除实体记录
masterDb.Delete(article);
//删除实体记录,显式指定主键名
masterDb.Delete(article, "article_id");
查询数据(立即执行)
var masterDb = new MasterDbContext(); //查询T_Article表所有记录
var articles = masterDb.FetchAll<Article>(); //指定条件查询,直接写参数值
var articles = masterDb.Fetch<Article>("select * from T_Article where Title=@p0 and Content=@p1", "hello", "hello word"); //指定条件查询,支持列表(实现了IEnumerable接口的)
var articles = masterDb.Fetch<Article>("select * from T_Article where article_id in @p0", new [] { , , }); //查询单条记录
masterDb.FirstOrDefault<Article>("select * from T_Article where article_id = @p0", ); //查询单列
var count = masterDb.ExecuteScalar<long>("select count(*) from T_Article"); //查询分页的结果(第1页,每页20条)
Paged<Article> paged = masterDb.Paged<Article>(, , "select * from T_Article where Title=@p0", "hello"); //Paged的定义如下
public class Paged<T> where T : new()
{
//当前页码
public int CurrentPage { get; set; } //总页数
public int TotalPages { get; set; } ///总记录数
public long TotalItems { get; set; } //每页记录数
public int ItemsPerPage { get; set; } //当前页记录列表
public List<T> Items { get; set; }
}
查询数据(延迟执行)
延迟查询使用Query,与Fetch不同的是Query返回的结果只有在使用时才会真正查询数据库
var masterDb = new MasterDbContext(); //延迟查询
var articles = masterDb.Query<Article>("select * from T_Article where Title=@p0", "hello");
动态查询条件
var title = "此变量来自用户输入"; var sb = new SqlBuilder();
sb.Append("select * from T_Article");
if(!string.IsNullOrEmpty(title))
sb.Append("where Title=@p0", title); var sql = sb.Build();
var articles = masterDb.Fetch<Article>(sql.Statement, sql.Parameters);
事务支持
using (var trans = this.GetTransaction())
{
//这里修改数据库 //提交事务
trans.Complete();
}
DapperPoco -- 基于Dapper的、轻量级的、高性能的、简单的、灵活的ORM框架的更多相关文章
- 分享自己写的基于Dapper的轻量级ORM框架~
1.说明 本项目是一个使用.NET Standard 2.0开发的,基于 Dapper 的轻量级 ORM 框架,包含基本的CRUD以及根据表达式进行一些操作的方法,目前只针对单表,不包含多表连接操作. ...
- ORM框架之------Dapper,Net下无敌的ORM
一,介绍:Dapper是一款轻量级ORM工具.如果你在小的项目中,使用Entity Framework.NHibernate 来处理大数据访问及关系映射,未免有点杀鸡用牛刀.你又觉得ORM省时省力,这 ...
- 基于轻量级ORM框架Dapper的扩展说明
这里简单的介绍一下本人基于Dapper作的一些简单的扩展,供大家参考. 为何要使用这款框架,相信大家看到下面排名就清楚了 其实在各大网站上,我们大概都会看到这样的一个对比效果图,在超过500次poco ...
- 【原创】基于.NET的轻量级高性能 ORM - TZM.XFramework
[前言] 接上一篇<[原创]打造基于Dapper的数据访问层>,Dapper在应付多表自由关联.分组查询.匿名查询等应用场景时不免显得吃力,经常要手写SQL语句(或者用工具生成SQL配置文 ...
- PetaPoco - 轻量级高性能的ORM框架(支持.NET Core)
我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db. 而且市面上的orm框架有很多,有重量级的Entity Framework,有 ...
- [开源] gnet: 一个轻量级且高性能的 Golang 网络库
Github 主页 https://github.com/panjf2000/gnet 欢迎大家围观~~,目前还在持续更新,感兴趣的话可以 star 一下暗中观察哦. 简介 gnet 是一个基于 Ev ...
- .net core 基于Dapper 的分库分表开源框架(core-data)
一.前言 感觉很久没写文章了,最近也比较忙,写的相对比较少,抽空分享基于Dapper 的分库分表开源框架core-data的强大功能,更好的提高开发过程中的效率: 在数据库的数据日积月累的积累下,业务 ...
- 基于netty轻量的高性能分布式RPC服务框架forest<下篇>
基于netty轻量的高性能分布式RPC服务框架forest<上篇> 文章已经简单介绍了forest的快速入门,本文旨在介绍forest用户指南. 基本介绍 Forest是一套基于java开 ...
- 基于netty轻量的高性能分布式RPC服务框架forest<上篇>
工作几年,用过不不少RPC框架,也算是读过一些RPC源码.之前也撸过几次RPC框架,但是不断的被自己否定,最近终于又撸了一个,希望能够不断迭代出自己喜欢的样子. 顺便也记录一下撸RPC的过程,一来作为 ...
随机推荐
- KB奇遇记(2):缘起
最早听到这家公司的名字,大概还是在好几年前. 正是2012年,之前的在一起灿坤待过的同事LY在这家公司当高层,正好公司规模大了,要上ERP项目.苦于公司没有这方面的人才,而内部IT又太差劲支撑不起来. ...
- 如何给 UILable 添加横线
类似淘宝上的原价现价,原价上一般都会有一条横线,这种效果怎么实现呢?其实相当的简单,我们只需要重写自定义的lable的 - (void)drawRect:(CGRect)rect 方法就行了. 具体实 ...
- 未来手机Alo即将问世!全息投影手机的新高峰!全息3d 网
文章来源:网络 编辑:大熊 [摘要]全息投影手机很早就开始炒,网络上的概念机也是丛出不穷,那么这款出自法国的概念机又是多么的奇葩?全息 3d 网带你一探究竟. 据外媒报道,在不久将来语 ...
- 比特(bit)、字,字节(B)存储单位之间的关系+其与操作系统位数的关系+不同编译器编译方式下数据类型的表示范围
1.在表示网络传输速度中与表示存储单位的不同: 表示存储单位时:1kB=1024B,但在网络中表示传输速度是1KB=1000B 2.下面介绍表示存储单位时的关系及其与操作系统位数的关系: 1B=8bi ...
- PLSQL DEVELOPER 使用的一些技巧【转】
1.登录后默认自动选中My Objects 默认情况下,PLSQL Developer登录后,Brower里会选择All objects,如果你登录的用户是dba,要展开tables目录,正常情况都需 ...
- JS闭包深入理解(理解篇)
看书的时候很是不明白为啥变量老是五,经过认真思考的出一下理解: function box() { var arr = []; for (var i = 0; i < 5; i++) { ...
- UI进阶 即时通讯之XMPP登录、注册
1.XMPP环境搭建 http://www.cnblogs.com/fearlessyyp/p/5506644.html 第一次打开可能会有点儿慢,图片很多,步骤很详细,祝搭建成功. 2.工程中添加X ...
- angular1.5 Components
如今前端界angular react vue三大框架并驾齐驱,其中有一个共同点就是组件化开发,这也符合w3c 推行Web Components的趋势.现如今不懂组件化开发的前端绝对不是好厨子.跳槽新公 ...
- Java内部类之匿名内部类
我们都知道Java中可以使用内部类,将一个类的定义放在另一个类的定义的内部,这就是内部类,但是匿名内部类往往使我们摸不着头脑,因为它并没有特定的名称,那么该如何使用它呢? 定义一个匿名内部类 pu ...
- js设计模式--迭代器模式
迭代器模式: 迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该方法中的内部表示.js中我们经常会封装一个each函数用来实现迭代器. 理解的意思:提供一个方法,去把对象的每一项按 ...