C#的dapper使用

C#的Dapper使用

標(biāo)簽(空格分隔): 未分類


摘要

  • 本文主要討論ORM技術(shù)和Dapper框架。
  • 先介紹ORM是什么——一種對象關(guān)系映射的技術(shù);再介紹為什么引入ORM——將關(guān)系型數(shù)據(jù)庫映射成面向?qū)ο缶幊?,簡化程序員的操作;而后介紹ORM具體怎么用——Dapper框架。
  • 在介紹dapper框架時我們引入了適配層概念,以期更易理解dapper的思想。
  • 最后介紹Dapper的安裝,基本用法,和復(fù)雜操作

ORM(Object Relation Mapping)

ORM是什么?

從字面理解,O是Object,對象;R是Relation,關(guān)系;M是Mapping,映射。所以,用一句話概括就是:ORM是一種對象關(guān)系映射的技術(shù)

為什么引入ORM?

我們平時所使用的大多數(shù)編程模型都是面向?qū)ο缶幊?,就是把我們研究的問題抽象出來分解成一個個對象,對象有屬性,方法等等,我們操作的是對象。比如一個學(xué)生就是一個對象,他有身高,體重等屬性,還有高數(shù)書這個屬性,高數(shù)書本身又是一個對象,高數(shù)書有價格,作者,主人等,該學(xué)生還有跑步,學(xué)習(xí)等方法。
我們可以操作學(xué)生跑步,可以操作學(xué)生學(xué)習(xí),可以操作學(xué)生再買一本英語書等等。我們還可以對學(xué)生的屬性高數(shù)書這個對象操作,例如把他丟棄。所以,我們操作的是對象,這就是面向?qū)ο缶幊獭?br> 而我們平時所使用的數(shù)據(jù)庫是關(guān)系型數(shù)據(jù)庫,他是從集合論等數(shù)學(xué)知識發(fā)展過來的,他講究集合,映射,六大范式等等,跟我們的面向?qū)ο笏枷氲姆庋b繼承多態(tài)不同,這兩者之間有著根本性的差異。
所以我們就存在一個問題,怎么去調(diào)和二者,如果能有一種技術(shù)把對象與數(shù)據(jù)庫對應(yīng)起來,我們編程就會方便許多。于是,ORM應(yīng)運而生,他就是為了解決對象與數(shù)據(jù)庫之間的差異所產(chǎn)生的一門技術(shù),用他可以把對象與數(shù)據(jù)庫建立一種映射,對于業(yè)務(wù)層的程序員,他不用管數(shù)據(jù)庫的結(jié)構(gòu),他只需要專注于他的業(yè)務(wù)邏輯去操作對象。至于對象怎么去變成元組進入數(shù)據(jù)庫,以及怎么從數(shù)據(jù)庫取數(shù)據(jù)變成對象,那是ORM自動解決的。

ORM怎么用?

既然ORM這么方便,我們該怎么去使用呢?其實每種語言,都有自己的ORM,各種ORM層出不窮,許多程序員還喜歡自己去寫一個ORM,這里哈希君只介紹C#下的Dapper框架。
在介紹Dapper之前,哈希君想跟大家討論一下適配層的概念,以期更好理解這個框架。


適配層

我們先來看看一臺計算機,他的最底層是硬件,然后在這之上加了一層操作系統(tǒng),操作系統(tǒng)負責(zé)對硬件的抽象和對資源的管理。這樣,無論我們的CPU是什么架構(gòu)的,網(wǎng)卡是什么廠商的,內(nèi)存條是多大的,只要有了操作系統(tǒng),他就可以把這些硬件全部抽象和管理出來,向上提供一個統(tǒng)一的接口,我們應(yīng)用層就無需管硬件了,只需要專注于接口就行了。所以這里操作系統(tǒng)就充當(dāng)了一個適配層的概念,他把底下各種亂七八糟不同的硬件全部適配出來給應(yīng)用層提供一個統(tǒng)一的接口,我們只要調(diào)這個接口就可以操作硬件了,而不用管這個硬件是怎么樣的,是不是方便多了。
同樣,瀏覽器也是一個適配層。無論你是Windows也好,Linux也好,筆記本也好,手機也好,瀏覽器把他們?nèi)窟m配出來,這樣網(wǎng)站就不用管這些細節(jié)了,他只需要專注于他的網(wǎng)站內(nèi)容,至于怎么渲染是瀏覽器的事情,瀏覽器會自動去適配的。所以瀏覽器又是各種操作系統(tǒng)的適配層。
那么,我們的Dapper也是一個適配層,他可以把錯綜復(fù)雜,恩怨糾葛的帶有各種約束的數(shù)據(jù)庫表抽象出來,向上提供一個統(tǒng)一的接口,對于程序員來說,只需要專注于業(yè)務(wù)邏輯即可。


Dapper

至此,終于到了本文的重點——Dapper,.NET下的一種ORM框架。

Dapper的安裝[1]

方法一:使用NuGet安裝
打開visual studio的項目,依次點擊工具,NuGet包管理器,管理解決方案的NuGet程序包;

LRHA{0TVII0W6B7VNHX3VGR.jpg

再點擊瀏覽,搜索dapper,點擊搜索結(jié)果中的Dapper,勾選項目選擇安裝;

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

解決方案管理器中點擊項目,查看引用,如果有Dapper,說明安裝成功。

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

方法二:直接在官網(wǎng)[2]下載源代碼,加入項目。這種方法哈希君沒有試,不過可以參考鏈接Dapper快速學(xué)習(xí)

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)

同樣我們在數(shù)據(jù)庫也有一個Person表,包含id,name,remark三個字段,其中id是主鍵自增。

而后我們在DAL層寫一個PersonDB類,提供對Person的基本訪問。connectionString是數(shù)據(jù)庫連接字符串,由配置文件讀取。

插入操作

將一個對象person插入數(shù)據(jù)庫的方法如圖。


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數(shù)據(jù),返回影響行數(shù)
/// </summary>
/// <param name="persons"></param>
/// <returns>影響行數(shù)</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>
/// 無參查詢所有數(shù)據(jù)
/// </summary>
/// <returns></returns>
public static List<Person> Query()
{
using (IDbConnection connection = new SqlConnection(connectionString))
{
    return connection.Query<Person>("select * from Person").ToList();
}
}

/// <summary>
/// 查詢指定數(shù)據(jù)
/// </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的復(fù)雜操作[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";
    //參數(shù)類型是Array的時候,dappper會自動將其轉(zhuǎn)化
    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";
    //參數(shù)類型是Array的時候,dappper會自動將其轉(zhuǎn)化
    return connection.Query<Person>(sql, new { ids }).ToList();
}
}

多語句操作

為此我們引入以下Book類,同樣在數(shù)據(jù)庫里設(shè)置這個表。

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操作

我們是面向?qū)ο缶幊蹋砸粋€對象里面會有許多其他子對象,這個子對象里面又有其自己的子對象,這種關(guān)系在數(shù)據(jù)庫里的表示就是外鍵。
比如我們有一本書book,它有主人person,book是一個對象,主人又是一個對象。

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

我們自然想要一個方法把數(shù)據(jù)庫里復(fù)雜的外鍵關(guān)系轉(zhuǎn)成我們需要的對象BookWithPerson,所有我們需要的信息都存在里面,取數(shù)據(jù)的時候只要找這個對象取數(shù)據(jù)就行了,比如我們需要一本書的主人的姓名,我們只需要bookWithPerson.Pers.Name。如果是一對多的關(guān)系我們用數(shù)組,如果是多對多我們加一層mapping。
現(xiàn)在我們想根據(jù)書的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的三個泛型參數(shù)分別是委托回調(diào)類型1委托回調(diào)類型2,返回類型。形參的三個參數(shù)分別是sql語句map委托,對象參數(shù)。所以整句的意思是先根據(jù)sql語句查詢;同時把查詢的person信息賦值給bookWithPerson.Pers,并且返回bookWithPerson;book是對象參數(shù),提供參數(shù)綁定的值。
最終整個方法返回BookWithPerson,這樣我們所需要的所有信息就有了。


有什么錯誤的地方歡迎指正!謝謝!


參考資料


  1. Dapper快速學(xué)習(xí) ?

  2. Dapper的git地址 ?

  3. Dapper,Net下無敵的ORM ?

  4. Dapper中的一些復(fù)雜操作 ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容