Dapper简明教程
Dapper是一款轻量级的ORM框架,有关Dapper优缺点的文章网上一大堆,这里小编就不再赘述啦。下面直接进入正题:
使用前准备
添加对Dapper的引用
在使用Dapper之前,我们要首先添加对Dapper的引用,这里小编使用NuGet来添加引用。因为小编使用的是MySQL数据库,所以也要在项目中添加对MySql.Data的引用。
Dapper是一款ORM框架,用于数据表和实体模型间的映射,所以在使用前我们还需要创建数据表和实体模型。
创建数据表
CREATE TABLE `t_schools` (
`Id` int(11) NOT NULL AUTO_INCREMENT ,
`Name` varchar(20) NOT NULL ,
`Address` varchar(50) NOT NULL ,
PRIMARY KEY (`Id`)
) CREATE TABLE `t_students` (
`Id` int(11) NOT NULL AUTO_INCREMENT ,
`Name` varchar(15) NOT NULL ,
`Number` varchar(15) NOT NULL ,
`SchoolId` int(11) NOT NULL ,
`Gender` enum('男','女','保密') NOT NULL ,
PRIMARY KEY (`Id`)
)
创建模型
class School
{
/*
若属性名和数据库字段不一致(不区分大小写)则查询不出数据,如果使用EF则可以通过Column特性
建立属性和数据表字段之间的映射关系,Dapper则不行
*/
//[Column("Name")]
public string Title { set; get; }
public string Address { set; get; }
} class Student
{
public string Name { set; get; }
public string Number { set; get; }
public int SchoolId { set; get; }
}
Dapper的基本用法
const string _connectionString = "Database=Dapper;Data Source=127.0.0.1;User Id=root;Password=root;pooling=false;CharSet=utf8;port=3306;";
using (IDbConnection dbConnection = new MySqlConnection(_connectionString))
{
dbConnection.Open();
//通过匿名类型插入单条数据
dbConnection.Execute("insert into t_schools(Name,Address) values(@Name,@Address)", new { Name = "西南大学", Address = "重庆市北碚区天生路2号" });
//批量插入数据
List<School> schools = new List<School>()
{
new School() {Address="China·BeiJing",Title="清华大学" },
new School() {Address="杭州",Title="浙江大学" },
new School() {Address="不知道,US?",Title="哈弗大学" }
};
//在执行参数化的SQL时,SQL中的参数(如@title可以和数据表中的字段不一致,但要和实体类型的属性Title相对应)
dbConnection.Execute("insert into t_schools(Address,Name) values(@address,@title);", schools);
//通过匿名类型批量插入数据
dbConnection.Execute("insert into t_schools(Address,Name) values(@address,@name)",
new[] {
new {Address="杨浦区四平路1239号",Name="同济大学"},
new {Address="英国",Name="剑桥"},
new {Address="美国·硅谷",Name="斯坦福大学"}
});
}
使用Dapper进行查询操作
默认情况下Dapper会将查询到的整个数据集放到内存中,可以在Query方法中通过参数buffered来设置是否将查询结果存放到内存中
查询结果映射到强类型
var schools = dbConnection.Query<School>("select * from t_schools where Name=@name", new { Name = "西南大学" });
foreach (var school in schools)
{
Console.WriteLine(school.Address);
}
查询变量如下图:

查询结果映射到匿名类型
在上面的查询中,我们将查询结果映射到了自定义的类型上。除了将查询结果映射到强类型之外,Dapper中还提供了匿名查询方式。
//查询结果result是匿名类型
var result = dbConnection.Query("select * from t_schools limit 0,3");
var resultList = result.AsList();
foreach (var l in resultList)
{
Console.WriteLine(l.Name);
}
查询结果如下:
in
var result = dbConnection.Query<Student>("select * from t_students where SchoolId in @schoolId", new { schoolId = new int[] { , } });
foreach (var r in result)
{
var ps = r.GetType().GetProperties();
foreach (var p in ps)
{
Console.Write(p.Name + "=" + p.GetValue(r) + " ");
}
Console.WriteLine();
}
查询结果如下:
between
var result = dbConnection.Query<School>("select Name,Address from t_schools where Id between @start and @end", new { start = , end = });
foreach (var r in result)
{
var ps = r.GetType().GetProperties();
foreach (var p in ps)
{
Console.Write(p.Name + "=" + p.GetValue(r) + " ");
}
Console.WriteLine();
}
查询结果如下:

join
使用join查询时需要用到Query方法中的splitOn参数,话说这个参数让小编纠结了很久才弄明白。关于splitOn参数的说明,可参考stackoverflow上的一篇文章Correct use of Multimapping in Dapper
var result = dbConnection.Query<Student, School, string>("select s.Name,sc.Address from t_students s,t_schools sc where s.SchoolId=sc.Id and binary sc.Address like '%BeiJing%'",
(s, sc) =>
{
return s.Name + " " + sc.Address;
},
/*
还有一点需要特别注意,泛型参数的顺序必须和SQL语句查询数据表的顺序一致,
即Student对应t_students表的查询结果s.Name,否则Query方法的查询结果
可能为null(这点也是困扰小编很久......)
*/
splitOn: "Address"
);
foreach (var r in result)
{
Console.WriteLine(r);
}
查询结果如下:

Dapper执行多条SQL语句
string sql = "select Address from t_schools;select SchoolId from t_students;select Name from t_students";
using (var multipleReader = dbConnection.QueryMultiple(sql))
{
//一次执行N条SQL语句则最多只能调用N次Read方法,否则抛异常:the reader has been disposed.
//Dapper读取查询结果数据的顺序必须要和查询语句中的查询顺序一致,否则可能读取不到数据
var schoolList = multipleReader.Read<School>();
foreach (var s in schoolList)
{
Console.Write(s.Address + " ");
}
Console.WriteLine();
var studentSchools = multipleReader.Read<Student>();
foreach (var s in studentSchools)
{
Console.Write(s.SchoolId + " ");
}
Console.WriteLine();
var studentNames = multipleReader.Read<Student>();
foreach (var s in studentNames)
{
Console.Write(s.Name + " ");
}
}
查询结果如下:

事务
使用Dapper执行事务倒是没有什么需要特别说明的。
using (IDbTransaction tran = dbConnection.BeginTransaction())
{
try
{
dbConnection.Execute("delete from t_schools where Id=3", transaction: tran);
throw new Exception();
tran.Commit();
}
catch
{
tran.Rollback();
}
}
存储过程
首先先创建一个存储过程
DROP PROCEDURE IF EXISTS `GetSchoolName`;
CREATE PROCEDURE `GetSchoolName`(in schoolId int,out scname varchar(20))
BEGIN
select `Name` into scname from t_schools where Id=schoolId;
select scname;
END;
然后在程序中调用存储过程
//在程序中调用存储过程时,存储过程名要小写,传递的参数名要和存储过程中的参数名一致(不区分大小写)
//连接字符串中的数据库名也要小写,否则抛异常:在数据库***中找不到存储过程×××
var parameters = new DynamicParameters();
parameters.Add("@scname", dbType: DbType.String, direction: ParameterDirection.Output);
parameters.Add("schoolid", , direction: ParameterDirection.Input);
var result = dbConnection.Query("getschoolname", parameters, commandType: CommandType.StoredProcedure);
执行结果如下:

从上图可以看出,返回值类型是Dapper中定义的DapperRow类型。
结语
- Dapper是一个轻量级的ORM框架,它是通过扩展IDbConnection接口来实现一系列的功能的。相比EF、NHibernate,它的功能较为简单。
- Dapper在执行查询语句时会缓存SQL语句的相关信息,这样就保证了Dapper拥有较高的性能(原文:Dapper caches information about every query it runs, this allow it to materialize objects quickly and process parameters quickly)。
以上内容是小编自己的一个学习总结,写出来一是作为自己的学习笔记,二是和广大网友分享。文中若有错误之处,还望各位读者能够指正。
参考文章:
Dapper
Dapper快速学习
Dapper中的一些复杂操作和inner join应该注意的坑
Dapper异常汇总
Correct use of Multimapping in Dapper
Dapper简明教程的更多相关文章
- 2013 duilib入门简明教程 -- 第一个程序 Hello World(3)
小伙伴们有点迫不及待了么,来看一看Hello World吧: 新建一个空的win32项目,新建一个main.cpp文件,将以下代码复制进去: #include <windows.h> #i ...
- 2013 duilib入门简明教程 -- 部分bug (11)
一.WindowImplBase的bug 在第8个教程[2013 duilib入门简明教程 -- 完整的自绘标题栏(8)]中,可以发现窗口最大化之后有两个问题, 1.最大化按钮的样式 ...
- 2013 duilib入门简明教程 -- 部分bug 2 (14)
上一个教程中提到了ActiveX的Bug,即如果主窗口直接用变量生成,则关闭窗口时会产生崩溃 如果用new的方式生成,则不会崩溃,所以给出一个临时的快速解决方案,即主窗口 ...
- 2013 duilib入门简明教程 -- 自绘控件 (15)
在[2013 duilib入门简明教程 -- 复杂控件介绍 (13)]中虽然介绍了界面设计器上的所有控件,但是还有一些控件并没有被放到界面设计器上,还有一些常用控件duilib并没有提供(比如 ...
- 2013 duilib入门简明教程 -- 事件处理和消息响应 (17)
界面的显示方面就都讲完啦,下面来介绍下控件的响应. 前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理.其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEG ...
- 2013 duilib入门简明教程 -- FAQ (19)
虽然前面的教程几乎把所有的知识点都罗列了,但是有很多问题经常在群里出现,所以这里再次整理一下. 需要注意的是,在下面的问题中,除了加上XML属性外,主窗口必须继承自WindowImpl ...
- Mac安装Windows 10的简明教程
每次在Mac上安装Windows都是一件非常痛苦的事情,曾经为了装Win8把整台Mac的硬盘数据都弄丢了,最后通过龟速系统恢复模式恢复了MacOSX(50M电信光纤下载了3天才把系统下载完),相信和我 ...
- Docker简明教程
Docker简明教程 [编者的话]使用Docker来写代码更高效并能有效提升自己的技能.Docker能打包你的开发环境,消除包的依赖冲突,并通过集装箱式的应用来减少开发时间和学习时间. Docker作 ...
- 2013 duilib入门简明教程 -- 总结 (20)
duilib的入门系列就到尾声了,再次提醒下,Alberl用的duilib版本是SVN上第个版本,时间是2013.08.15~ 这里给出Alberl最后汇总的一个工程,戳我下载,效 ...
随机推荐
- js判断只能输入数字和只能输入
JS判断只能是数字和小数点 1.文本框只能输入数字代码(小数点也不能输入) <input onkeyup="this.value=this.value.replace(/\D/g,'' ...
- html 5 实现拖放效果
在html5中要实现拖放操作,相对于以前通过鼠标操作实现,要简单得多,数据安全性也更有保障.只需要以下几步即可. 给被拖拽元素添加draggable属性,如果是文件拖放. 在拖拽元素的dragstar ...
- Mono 3.2 上跑NUnit测试
NUnit是一款堪与JUnit齐名的开源的回归测试框架,供.net开发人员做单元测试之用,可以从www.nunit.org网站上免费获得,最新版本是2.5.Mono 3.2 源码安装的,在/usr/b ...
- Scala 笔记
环境 1. Intellij Idea 2. Scala 插件 3. http://scala-lang.org/ 教程: idea官方教程: https://www.jetbrains.com/he ...
- 剑指Offer面试题:17.树的子结构
一.题目:树的子结构 题目:输入两棵二叉树A和B,判断B是不是A的子结构.例如下图中的两棵二叉树,由于A中有一部分子树的结构和B是一样的,因此B是A的子结构. 该二叉树的节点定义如下,这里使用C#语言 ...
- 为什么google bazel构建工具流行不起来
作者Jack47 转载请保留作者和原文出处 之前博主写了系列文章Google软件构建工具Bazel原理及使用方法介绍.最近使用了一段时间后,觉得这个东西不是一种通用的构建工具,很难对接到情况复杂的大的 ...
- 如何在 ASP.NET MVC 中集成 AngularJS(2)
在如何在 ASP.NET MVC 中集成 AngularJS(1)中,我们介绍了 ASP.NET MVC 捆绑和压缩.应用程序版本自动刷新和工程构建等内容. 下面介绍如何在 ASP.NET MVC 中 ...
- ASP.NET MVC 从零开始 - 自动化部署(其二)
这篇文章是从我的 github 博客 http://lxconan.github.io 导入的. 这是这个系列的第五篇了,前四篇请参见: ASP.NET MVC 从零开始 – Create and R ...
- 使用变量 数据类型转换 逻辑控制语句(begin ...end; case...end; if...else; while)
一:变量 变量分为局部变量和全局变量 (全局变量是系统自定的,是不可手动给值的,若想自己定义全局变量可考虑创建全局临时表!) 局部变量的定义: declare @变量名 数据类型 (局部变量只能 ...
- JQuery图片切换动画效果
由于博主我懒,所以页面画的比较粗糙,但是没关系,因为我主要讲的是如何实现图片动画切换. 思路:想必大家都逛过淘宝或者其他的一些网站,一般都会有图片动画切换的效果,那是怎样实现的呢?博主我呢,技术不是很 ...