Dapper:一款轻量级ORM框架快速学习入门

  我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db,而且市面上的orm框架有很多,其中有一个框架叫做Dapper,而且被称为the king of ORM。Dapper是.NET下一个micro的ORM,它和Entity Framework或Nhibnate不同,属于轻量级的,并且是半自动的。Dapper只有一个代码文件,完全开源,你可以放在项目里的任何位置,来实现数据到对象的ORM操作,体积小速度快。 使用ORM的好处是增、删、改很快,不用自己写sql,因为这都是重复技术含量低的工作,还有就是程序中大量的从数据库中读数据然后创建model,并为model字段赋值。这些ORM都可以轻松给你搞定。ORM给我们开发带来便利时,性能也是一个让我们不得不考虑的问题。一般的ORM性能和直接写原生的sql比都差不少,但是Dapper性能还很错,甚至和DbHelperSQL方式性能高出很多。

Dapper的优势
  Dapper是一个轻型的ORM类。代码就一个SqlMapper.cs文件,编译后体积小。
  Dapper很快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
  Dapper支持多数据库。诸如:Mysql,SqlLite,Mssql系列,Oracle等一系列的数据库。
  Dapper的R支持多表并联的对象。支持一对多 多对多的关系。并且没侵入性,想用就用,不想用就不用,无XML无属性,代码以前怎么写现在还怎么写。
  Dapper原理通过Emit反射IDataReader的序列队列,来快速的得到和产生对象,性能高。
  Dapper支持net2.0及以上版本
  Dapper语法十分简单,并且无须迁就数据库的设计。

————————————————

 一:为什么选择Dapper

1. 性能优越:

    其实在各大网站上,我们大概都会看到这样的一个对比效果图,在超过500次poco serialization的过程中所表现的性能,我们发现dapper是第二名,当然第一名谁也无法超越,越底层的当然久越快,同时也就越麻烦。

 

2. 支持多数据库

      支持多数据库的本质是因为Dapper是对IDBConnection接口进行了方法扩展,比如你看到的SqlMapper.cs,一旦你这样做了,我们也知道,

SqlConnection,MysqlConnection,OracleConnection都是继承于DBConnection,而DBConnection又是实现了IDBConnection的接口,对吧。。。

 

二:安装Dapper

    install dapper的方式通常有两种: 

1. 通过nuget进行安装

打开visual studio的项目,依次点击工具NuGet包管理器管理解决方案的NuGet程序包; 

再点击浏览搜索dapper点击搜索结果中的Dapper勾选项目选择安装

解决方案管理器中点击项目查看引用,如果有Dapper,说明安装成功。 

 

   如果你不知道怎么用nuget进行安装,或者不知道install-package是什么,可以在browser上找一下,比如下面这样:

 

然后我们copy到package console 试试看。

 

 

2. 在github上获取源码。

   为什么要获取源码,是因为用ilspy调试dapper的源码太费劲了,毕竟现在都是异步编程了,从ilspy中看都是匿名方法很多都无法渗透,废话不多

说,我们只要把Dapper文件夹拉出来然后copy到我们的solution就可以了,如下图:

 

三:快速CURD操作

   其实对数据库的操作莫过于CURD,在进行操作之前我们再配一个Users表。

 

1. 配置Users表、Product表

复制代码
--Users表
CREATE TABLE [dbo].[Users]( [UserID] [int] IDENTITY(1,1) NOT NULL, [UserName] [varchar](50) NULL, [Email] [varchar](100) NULL, [Address] [varchar](100) NULL, CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED ( [UserID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]

--Product表
CREATE TABLE [dbo].[Product](
[ProductID] [int] IDENTITY(1,1) NOT NULL,
[ProductName] [varchar](220) NULL,
[ProductDesc] [varchar](220) NULL,
[UserID] [int] NULL,
[CreateTime] [datetime] NULL,
CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED
(
[ProductID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
复制代码

 

2. Insert操作

  通常来说,有两种insert操作:

(1)单条insert操作:以下是一个简单的参数化insert,而且还可以塞入匿名类型,对吧,跟原始的SqlParameter相比,是不是简单的多!!!

复制代码
     static void Main(string[] args)
     {
          var connectionStr= new SqlConnection("Data Source=.;Initial Catalog=DataMip;Integrated Security=True;MultipleActiveResultSets=True");
using (IDbConnection connection = new SqlConnection(connectionStr)) { connection.Execute("insert into Users values(@UserName,@Email,@Address)", new { UserName = "IvanJiang", Email = "test@163.com", Address = "上海" }); } }
复制代码

 

(2) InsertBulk操作

     既然是Bulk操作,那肯定就是批量插入了,我们要做的就是将上面这个 ”匿名对象" 变成 ”匿名对象集合“ 就可以了。为了方便操作,这里定义一个Users类,比如下面这样。。。

复制代码
using (IDbConnection connection = new SqlConnection(connectionStr))
{
  var list = Enumerable.Range(0, 10).Select(i => new User()
    {
      UserName = "test" + i.ToString(),
      Email = "test" + i.ToString() + "@qq.com",
      Address = "上海"
    });
  connection.Execute("insert into Users values(@UserName,@Email,@Address)",list);
}
复制代码

 

2. Query操作

   其实在Dapper在query上提供的的文章太多了。。。这篇我们就按照最简单的参数化查询就好了。。。比如我要找到username=jack的记录,如下:

using (SqlConnection conn = new SqlConnection(connectionStr))
{
   var res = conn.Query<User>("select * from Users where UserName=@UserName", new { UserName = "test" }).ToList();
   res.ForEach(x => Console.WriteLine(String.Format("UserName={0},Email={1}, Address={2}", x.UserName,x.Email,x.Address)));
}

其中最大的亮点就在于能够自动化mapper到我们object上面来,这是我们DataReader所不能办到的

 

3.update操作

  这种操作方式,我们还是使用Execute方法来实现,和insert是一种套路的哦。

using (SqlConnection conn = new SqlConnection(connectionStr))
{
  conn.Execute("update Users set Address='上海' where UserName=@UserName", new { UserName = "test" });
  var res1 = conn.Query<User>("select * from Users where UserName=@UserName", new { UserName = "IvanJiang" }).ToList();   res1.ForEach(x => Console.WriteLine(String.Format("UserName={0},Email={1}, Address={2}", x.UserName, x.Email, x.Address))); }

 

4. delete操作

    这里我还是采用参数化的形式来删除UserID=10这条记录,方式如下:

using (SqlConnection conn = new SqlConnection(connectionStr))
{
   conn.Execute("delete from Users where UserName=@UserName", new { UserName = "IvanJiang" });
}

 当然Dapper好玩的地方多着呢,这篇只是一个入门而已,希望本篇对大家有帮助~~~

 

5.in操作

  很多时候我们在manipulate table的时候,或多或少的都会用到 ”in关键字”,比如:我要找到User表中Email in ('5qq.com','8qq.com') 

分类: ORM
复制代码
using (SqlConnection conn = new SqlConnection(connectionStr))
{
   var sql = "select * from Users where UserID in @UserIDs";

    //参数类型是Array的时候,dappper会自动将其转化
    var res = conn.Query<User>(sql, new { UserIDs = new int[3] { 4, 5, 6 } }).oList();
    res.ForEach(x => Console.WriteLine(String.Format("UserName={0},Email={1}, Address={2}", x.UserName, x.Email, x.Address)));

 }

复制代码

 6.多条sql一起执行

     有时候我们会想在一条sql中灌入很多的snippet sql,然后让其一起执行,比如:select ... from marketing where  id in (....); select .... from eventmarketing where in (...)类似这样的语句。

 

复制代码
  using (SqlConnection conn = new SqlConnection(connectionStr))

  {

    var sqls = "select * from Product; select * from Users";
    var multiReader = conn.QueryMultiple(sqls);
    var productList = multiReader.Read<Product>().ToList();
    var userList = multiReader.Read<User>().ToList();
    multiReader.Dispose();

 

    userList.ForEach(x => Console.WriteLine(String.Format("UserName={0},Email={1}, Address={2}", x.UserName, x.Email, x.Address)));
    productList.ForEach(x => Console.WriteLine(String.Format("UserName={0},Email={1}, Address={2}", x.UserName, x.Email, x.Address)));
  }

复制代码

 

7.多表join操作

     不管sql写的多么好或者多么烂,接触一个月还是接触到十年,都必然跑不了多表查询,那么在多表查询上dapper该如何使用呢???比如说我要找到2015-12-12之后的商品信息和个人信息,很显然这是一个多表查询,可以先来看一下users和product的关系。

可以发现其实他们有一个外键关系,然后我们在Product Entity上做一下小修改,将Users作为Product的一个entity property。。。

   public class Product
    {
        public int ProductID { get; set; }
        public string ProductName { get; set; }
        public string ProductDesc { get; set; }
        public Users UserOwner { get; set; }
        public string CreateTime { get; set; }
    }

 有了这些储备,我们大概就可以写出如下的sql。

复制代码
   using (SqlConnection conn = new SqlConnection(connectionStr))
  { var sql = @"select  p.ProductName,p.CreateTime,u.UserName from   Product as p join   Users as u on    p.UserID = u.UserID where p.CreateTime > '2015-12-12'"; var result = conn.Query<Product, Users, Product>(sql, (product, users) => { product.UserOwner = users;
                        return product; }); }
复制代码

 这是结果就是报错,如下:

 

从错误信息中可以看到:当你使用multi-mapping的时候要确保设置了splitOn参数,除了Id。。。从这句话中好像也看不出什么名堂,也就是说

除了Id,你都需要设置SplitOn参数,好吧,这是逼着哥哥看源代码。。。。看看SplitOn到底是个什么样的鸟玩法。。。然后我从Call Stack往上

面找,发现了非常”至关重要“的一段话。

 

    然来splitOn就是Dapper对DataReader进行”从右到左“的扫描,这样就可以从sequent中获取到一个subsequent,然后遇到设置的splitOn就停止。原来是这样,就可以将splitOn设置为”UserName“就好了。比如下面这样。。。

复制代码
  using (SqlConnection conn = new SqlConnection(connectionStr))
  { var connection = new SqlConnection("Data Source=.;Initial Catalog=Datamip;Integrated Security=True;MultipleActiveResultSets=True"); var sql = @"select p.ProductName,p.CreateTime,u.UserName from Product as p join Users as u on p.UserID = u.UserID where p.CreateTime > '2015-12-12'; "; var result = connection.Query<Product, Users, Product>(sql, (product, users) => { product.UserOwner = users;
                        return product; },
                      splitOn: "UserName"); } 
复制代码

当然如果你觉得我上面说的太啰嗦了,注意事项还tmd的多,又是泛型,又是Lambda的。。。你也可以不指定这些具体Type,而默认使用

dynamic也是可以的,比如下面这样:

 

8.持存储过程

   对于存储过程,也是一个不得不说的话题,Dapper同样也是可以执行存储过程,只需要在Query中的CommandType中标记一下当前就是一个StoredProcedure.

比如现在在Users表上创建一个简单的StoredProcedure。

复制代码
USE [TEST]
GO
/****** Object:  StoredProcedure [dbo].[sp_GetUsers]    Script Date: 09/02/2016 09:14:04 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[sp_GetUsers]  
 @id int   
as  
begin   
select * from Users where UserID = @id ;   
end 
复制代码

 

在这里,我们需要向存储过程塞入一个@id参数,返回具体的Users EntityList,好了,下面再看一下Query如何构造。

复制代码
 using (SqlConnection conn = new SqlConnection(connectionStr))

{
  var res = conn.Query<User>("sp_GetUsers", new { id = 5 }, commandType: CommandType.StoredProcedure).ToList();
  res.ForEach(x => Console.WriteLine(String.Format("UserName={0},Email={1}, Address={2}", x.UserName, x.Email, x.Address)));

} 

复制代码

 

到这里,感觉用Dapper是不是就这么简单,先就说到这里,希望对大家有帮助。

 

摘自于:https://www.jianshu.com/p/c4ca2989d26a

 

 

posted @   燕过留痕  阅读(4578)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示