为什么要重复造轮子

因为现有的轮子都在某些方面不太令我满意,下面我来一一点评一下,欢迎拍砖。

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的一切优点,同时也弥补了它的不足,它有如下特点:

  1. 高性能(与Dapper一致),以热启动后计算(第一次启动有缓存过程)
  2. 像EF一样使用简单,也可像Dapper一样灵活使用原生SQL
  3. 支持使用Fluent API定义实体映射
  4. 内部模块化灵活、可扩展

现已将其开源并放到了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框架的更多相关文章

  1. 分享自己写的基于Dapper的轻量级ORM框架~

    1.说明 本项目是一个使用.NET Standard 2.0开发的,基于 Dapper 的轻量级 ORM 框架,包含基本的CRUD以及根据表达式进行一些操作的方法,目前只针对单表,不包含多表连接操作. ...

  2. ORM框架之------Dapper,Net下无敌的ORM

    一,介绍:Dapper是一款轻量级ORM工具.如果你在小的项目中,使用Entity Framework.NHibernate 来处理大数据访问及关系映射,未免有点杀鸡用牛刀.你又觉得ORM省时省力,这 ...

  3. 基于轻量级ORM框架Dapper的扩展说明

    这里简单的介绍一下本人基于Dapper作的一些简单的扩展,供大家参考. 为何要使用这款框架,相信大家看到下面排名就清楚了 其实在各大网站上,我们大概都会看到这样的一个对比效果图,在超过500次poco ...

  4. 【原创】基于.NET的轻量级高性能 ORM - TZM.XFramework

    [前言] 接上一篇<[原创]打造基于Dapper的数据访问层>,Dapper在应付多表自由关联.分组查询.匿名查询等应用场景时不免显得吃力,经常要手写SQL语句(或者用工具生成SQL配置文 ...

  5. PetaPoco - 轻量级高性能的ORM框架(支持.NET Core)

    我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db. 而且市面上的orm框架有很多,有重量级的Entity Framework,有 ...

  6. [开源] gnet: 一个轻量级且高性能的 Golang 网络库

    Github 主页 https://github.com/panjf2000/gnet 欢迎大家围观~~,目前还在持续更新,感兴趣的话可以 star 一下暗中观察哦. 简介 gnet 是一个基于 Ev ...

  7. .net core 基于Dapper 的分库分表开源框架(core-data)

    一.前言 感觉很久没写文章了,最近也比较忙,写的相对比较少,抽空分享基于Dapper 的分库分表开源框架core-data的强大功能,更好的提高开发过程中的效率: 在数据库的数据日积月累的积累下,业务 ...

  8. 基于netty轻量的高性能分布式RPC服务框架forest<下篇>

    基于netty轻量的高性能分布式RPC服务框架forest<上篇> 文章已经简单介绍了forest的快速入门,本文旨在介绍forest用户指南. 基本介绍 Forest是一套基于java开 ...

  9. 基于netty轻量的高性能分布式RPC服务框架forest<上篇>

    工作几年,用过不不少RPC框架,也算是读过一些RPC源码.之前也撸过几次RPC框架,但是不断的被自己否定,最近终于又撸了一个,希望能够不断迭代出自己喜欢的样子. 顺便也记录一下撸RPC的过程,一来作为 ...

随机推荐

  1. eclipse自定义new建

    Window->Perspective->Customize Perspective->Shortcuts   找到适合的选中然后OK即可

  2. java实现解析二进制文件(字符串、图片)

    1.需求说明,实现细节要求: 解析二进制文件 files\case10\binary,其中包含一个字符串和一张图片,数据文件格式为字符串数据长度(2字节)+字符串内容+图片数据长度(4字节)+图片数据 ...

  3. C语言一维数组转换为二维数组

    一维转二维代码示例: #include <stdio.h> #include <stdlib.h> #define ROW 3 #define COL 2 int main(i ...

  4. PAT乙级 1065. 单身狗(25) by Python

    1065. 单身狗(25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue "单身狗"是中文对 ...

  5. Sqlserver 链接服务器和同义词

    在数据库的日常维护中,经常会遇到跨服务器的数据传输. 例如A服务器上的数据每天要从B服务器上去获取数据,然后插入到自己的服务器上.这种情况就要用到链接服务器了. 接下来,我就把我本机当作服务器A,17 ...

  6. php in_array语法

    bool in_array ( mixed $needle , array $haystack [, bool $strict ] ) 返回值为直或假       var_dump(in_array( ...

  7. HTML中三种定位relative,absolute,fixed后,盒子的百分比宽度及位置易错点

    1 . 相对定位relative:顾名思义,相对定位是相对于自己的位置来进行偏移,如下图: 以盒子中心为基准,为每条边的正方向,例: 向右移动20px : 代码为left:20px;或者right:- ...

  8. linux文件和目录权限

    linux系统文件和目录的权限说明 文件权限是Linux系统的第一道安全防线,基本的权限有读取(r).写入(w)和执行(x): 文件访问模式 读取:用户能够读取文件信息,查看文件内容. 写入:用户可以 ...

  9. 谈JS中的作用域链与原型链(1)

    学习前端也有一段时间了,觉得自己可以与大家分享一些我当初遇到疑惑的东西,希望能给对此问题有疑惑的朋友带来一点帮助. 先来普及一下JS的概念(不要嫌我啰嗦,可能一些朋友开始学习JS是跟着视频和写好的代码 ...

  10. fir.im Weekly - 8 个不能错过的 iOS / Android 技术分享

    本期 fir.im Weekly 收集了 2 月下旬新鲜出炉的 iOS /Android 技术分享.源码等,iOS 中图片技术的解压缩.逆向实战.iOS SDK 实践,Android架构思考.Andr ...