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);
}
查询变量

有上图我们可以看到,因为School类中的Title属性在数据库中没有与之对应的字段,所以Title的值为null。


查询结果
  • 查询结果映射到匿名类型

在上面的查询中,我们将查询结果映射到了自定义的类型上。除了将查询结果映射到强类型之外,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[] { 2, 3 } });
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 = 2, end = 4 });
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", 6, 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,422评论 0 4
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 概述 当代的互联网的服务,通常都是用复杂的、大规模分布式集群来实现的。互联网应用构建在不同的软件模块集上,这些软件...
    咖灰阅读 5,873评论 0 16
  • 《向前一步》谢丽尔 · 桑德伯格 现任Facebook首席运营官。福布斯前50名“最有力量”的商业女精英之一。曾登...
    何阿予阅读 267评论 0 3