C#的Dapper使用

 转自https://www.jianshu.com/p/c4ca2989d26a


摘要

  • 本文主要讨论ORM技术和Dapper框架。
  • 先介绍ORM是什么——一种对象关系映射的技术;再介绍为什么引入ORM——将关系型数据库映射成面向对象编程,简化程序员的操作;而后介绍ORM具体怎么用——Dapper框架。
  • 在介绍dapper框架时我们引入了适配层概念,以期更易理解dapper的思想。
  • 最后介绍Dapper的安装,基本用法,和复杂操作

ORM(Object Relation Mapping)

ORM是什么?

从字面理解,O是Object,对象;R是Relation,关系;M是Mapping,映射。所以,用一句话概括就是:ORM是一种对象关系映射的技术

为什么引入ORM?

我们平时所使用的大多数编程模型都是面向对象编程,就是把我们研究的问题抽象出来分解成一个个对象,对象有属性,方法等等,我们操作的是对象。比如一个学生就是一个对象,他有身高,体重等属性,还有高数书这个属性,高数书本身又是一个对象,高数书有价格,作者,主人等,该学生还有跑步,学习等方法。
我们可以操作学生跑步,可以操作学生学习,可以操作学生再买一本英语书等等。我们还可以对学生的属性高数书这个对象操作,例如把他丢弃。所以,我们操作的是对象,这就是面向对象编程。
而我们平时所使用的数据库是关系型数据库,他是从集合论等数学知识发展过来的,他讲究集合,映射,六大范式等等,跟我们的面向对象思想的封装继承多态不同,这两者之间有着根本性的差异。
所以我们就存在一个问题,怎么去调和二者,如果能有一种技术把对象与数据库对应起来,我们编程就会方便许多。于是,ORM应运而生,他就是为了解决对象与数据库之间的差异所产生的一门技术,用他可以把对象与数据库建立一种映射,对于业务层的程序员,他不用管数据库的结构,他只需要专注于他的业务逻辑去操作对象。至于对象怎么去变成元组进入数据库,以及怎么从数据库取数据变成对象,那是ORM自动解决的。

ORM怎么用?

既然ORM这么方便,我们该怎么去使用呢?其实每种语言,都有自己的ORM,各种ORM层出不穷,许多程序员还喜欢自己去写一个ORM,这里哈希君只介绍C#下的Dapper框架。
在介绍Dapper之前,哈希君想跟大家讨论一下适配层的概念,以期更好理解这个框架。


适配层

我们先来看看一台计算机,他的最底层是硬件,然后在这之上加了一层操作系统,操作系统负责对硬件的抽象和对资源的管理。这样,无论我们的CPU是什么架构的,网卡是什么厂商的,内存条是多大的,只要有了操作系统,他就可以把这些硬件全部抽象和管理出来,向上提供一个统一的接口,我们应用层就无需管硬件了,只需要专注于接口就行了。所以这里操作系统就充当了一个适配层的概念,他把底下各种乱七八糟不同的硬件全部适配出来给应用层提供一个统一的接口,我们只要调这个接口就可以操作硬件了,而不用管这个硬件是怎么样的,是不是方便多了。
同样,浏览器也是一个适配层。无论你是Windows也好,Linux也好,笔记本也好,手机也好,浏览器把他们全部适配出来,这样网站就不用管这些细节了,他只需要专注于他的网站内容,至于怎么渲染是浏览器的事情,浏览器会自动去适配的。所以浏览器又是各种操作系统的适配层。
那么,我们的Dapper也是一个适配层,他可以把错综复杂,恩怨纠葛的带有各种约束的数据库表抽象出来,向上提供一个统一的接口,对于程序员来说,只需要专注于业务逻辑即可。


Dapper

至此,终于到了本文的重点——Dapper,.NET下的一种ORM框架。

Dapper的安装[1]

方法一:使用NuGet安装
打开visual studio的项目,依次点击工具NuGet包管理器管理解决方案的NuGet程序包

LRHA{0TVII0W6B7VNHX3VGR.jpg

 

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

DTL$~J)8V@{C5}2BFJN@$8O.png

 

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

Z6A3%}8V8)O1MT@@~PE`MCH.png

 

方法二:直接在官网[2]下载源代码,加入项目。这种方法哈希君没有试,不过可以参考链接Dapper快速学习

Dapper的基本用法[3]

首先,我们在Model层写一个Person类,他有ID,Name,Remark。
![(UBQ}]CQ32{{VW`1EGPJ5MQ.png](http://upload-images.jianshu.io/upload_images/4052700-01cbfcab5e889f51.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

同样我们在数据库也有一个Person表,包含id,name,remark三个字段,其中id是主键自增。

而后我们在DAL层写一个PersonDB类,提供对Person的基本访问。connectionString是数据库连接字符串,由配置文件读取。

插入操作

将一个对象person插入数据库的方法如图。

 

Q_{~JX7~%Q3512XFJM9DG{W.png

 

插入代码文本如下。@Name的意思是自动将person里的Name值绑定上去。

public static int Insert(Person person)
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    return connection.Execute("insert into Person(Name,Remark) values(@Name,@Remark)", person);
}
}

批量插入:

/// <summary>
/// 批量插入Person数据,返回影响行数
/// </summary>
/// <param name="persons"></param>
/// <returns>影响行数</returns>
public static int Insert(List<Person> persons)
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    return connection.Execute("insert into Person(Name,Remark) values(@Name,@Remark)", persons);
}
}

删除操作

public static int Delete(Person person)
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    return connection.Execute("delete from Person where id=@ID", person);
}
}

public static int Delete(List<Person> persons)
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    return connection.Execute("delete from Person where id=@ID", persons);
}
}

修改操作

public static int Update(Person person)
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    return connection.Execute("update Person set name=@name where id=@ID", person);
}
}

public static int Update(List<Person> persons)
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    return connection.Execute("update Person set name=@name where id=@ID", persons);
}
}

查询操作

/// <summary>
/// 无参查询所有数据
/// </summary>
/// <returns></returns>
public static List<Person> Query()
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    return connection.Query<Person>("select * from Person").ToList();
}
}

/// <summary>
/// 查询指定数据
/// </summary>
/// <param name="person"></param>
/// <returns></returns>
public static Person Query(Person person)
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    return connection.Query<Person>("select * from Person where id=@ID", person).SingleOrDefault();
}
}

Dapper的复杂操作[4]

查询的In操作

/// <summary>
/// In操作
/// </summary>
public static List<Person> QueryIn()
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    var sql = "select * from Person where id in @ids";
    //参数类型是Array的时候,dappper会自动将其转化
    return connection.Query<Person>(sql, new { ids = new int[2] { 1, 2 }, }).ToList();
}
}

public static List<Person> QueryIn(int[] ids)
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    var sql = "select * from Person where id in @ids";
    //参数类型是Array的时候,dappper会自动将其转化
    return connection.Query<Person>(sql, new { ids }).ToList();
}
}

多语句操作

为此我们引入以下Book类,同样在数据库里设置这个表。

public class Book
{
public int ID { get; set; }
public int PersonID { get; set; }
public string BookName { get; set; }
}
/// <summary>
/// 多语句操作
/// </summary>
public static void QueryMultiple()
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    var sql = "select * from Person; select * from Book";
    var multiReader = connection.QueryMultiple(sql);
    var personList = multiReader.Read<Person>();
    var bookList = multiReader.Read<Book>();
    multiReader.Dispose();
}
}

Join操作

我们是面向对象编程,所以一个对象里面会有许多其他子对象,这个子对象里面又有其自己的子对象,这种关系在数据库里的表示就是外键。
比如我们有一本书book,它有主人person,book是一个对象,主人又是一个对象。

public class BookWithPerson
{
public int ID { get; set; }
public Person Pers { get; set; }
public string BookName { get; set; }
}

我们自然想要一个方法把数据库里复杂的外键关系转成我们需要的对象BookWithPerson,所有我们需要的信息都存在里面,取数据的时候只要找这个对象取数据就行了,比如我们需要一本书的主人的姓名,我们只需要bookWithPerson.Pers.Name。如果是一对多的关系我们用数组,如果是多对多我们加一层mapping。
现在我们想根据书的ID查询书的信息,包括主人信息。那么

public static BookWithPerson QueryJoin(Book book)
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    var sql = @"select b.id,b.bookName,p.id,p.name,p.remark
                        from Person as p
                        join Book as b
                        on p.id = b.personId
                        where b.id = @id;";
    var result = connection.Query<BookWithPerson, Person, BookWithPerson>(sql,
        (bookWithPerson, person) =>
        {
            bookWithPerson.Pers = person;
            return bookWithPerson;
        },
        book);
    //splitOn: "bookName");
    return (BookWithPerson)result;
}
}

其中,Query的三个泛型参数分别是委托回调类型1委托回调类型2返回类型。形参的三个参数分别是sql语句map委托对象参数。所以整句的意思是先根据sql语句查询;同时把查询的person信息赋值给bookWithPerson.Pers,并且返回bookWithPerson;book是对象参数,提供参数绑定的值。
最终整个方法返回BookWithPerson,这样我们所需要的所有信息就有了。



作者:哈希君
链接:https://www.jianshu.com/p/c4ca2989d26a
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。


 

  • 3
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值