DapperPoco
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", 1); //更新除主键外的所有列
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 = 1,
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", 1);
//删除实体记录
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 [] { 1, 2, 3 }); //查询单条记录
masterDb.FirstOrDefault<Article>("select * from T_Article where article_id = @p0", 1); //查询单列
var count = masterDb.ExecuteScalar<long>("select count(*) from T_Article"); //查询分页的结果(第1页,每页20条)
Paged<Article> paged = masterDb.Paged<Article>(1, 20, "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的更多相关文章
- DapperPoco -- 基于Dapper的、轻量级的、高性能的、简单的、灵活的ORM框架
为什么要重复造轮子 因为现有的轮子都在某些方面不太令我满意,下面我来一一点评一下,欢迎拍砖. Entity Framework 我喜欢傻瓜化使用方式的框架,同时又不失灵活性. EF虽然使用起来足够简单 ...
随机推荐
- Altium Designer中死铜的问题
- JS学习笔记 - fgm练习 - 输入数字求和 正则replace onkeyup事件
<style> body{font-size: 12px;} .outer{ width: 500px; margin: 0 auto; } span{ color: #999; } in ...
- Ab工具基本使用
Ab简介 ab是apache自带的压力测试工具,ab是apachebench命令的缩写. ab不仅可以对apache服务器进行网站访问压力测试,也可以对或其它类型的服务器进行压力测试. ab是一个ht ...
- 【习题 3-12 UVA - 11809】Floating-Point Numbers
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] \(A*10^B = temp[M]*2^{2^E-1}\) 两边取一下对数 得到 \(lg_A+B = lg_{temp[M]} ...
- 10.4 android输入系统_框架、编写一个万能模拟输入驱动程序、reader/dispatcher线程启动过程源码分析
1. 输入系统框架 android输入系统官方文档 // 需FQhttp://source.android.com/devices/input/index.html <深入理解Android 卷 ...
- Java与模式:装饰(Decorator)模式
装饰模式使用被装饰类的一个子类的实例.把client的调用委派到被装饰类,装饰模式的关键在于这样的扩展是全然透明的. 装饰模式在Java种使用也非常广泛,比方我们在又一次定义button.对话框等 ...
- UCloud上LAMP小型站点搭建与測试
文件夹 介绍 LAMP环境搭建 打开UCloud防火墙 WordPress安装 应用測试 介绍 本篇博客旨在通过介绍搭建一个WordPress博客的过程介绍在UCloud的云主机(UHOST)上搭建单 ...
- TreeView控件的展开与折叠
在窗体中添加一个TreeView控件,设置CheckBox属性为True,绑定数据 Archive jkj = new Archive();//自定义类 public void Bind ...
- 数据结构与算法实验题 4.2 Who is the strongest
数据结构与算法实验题 4.2 Who is the strongest ★实验任务 在神奇的魔法世界,召唤师召唤了一群的魁偶.这些魁偶排成一排,每个魁偶都有一个 战斗值.现在该召唤师有一个技能,该技能 ...
- 看朋友日志发现的一个ios下block相关的内存管理问题,非常奇怪,请大家帮忙一起来回答!
http://blog.csdn.net/fengsh998/article/details/38090205 这篇文章以下是我的回复.相同的代码仅仅是把变量的定义从局部变量改为类的成员变量就发现了非 ...