轉自:http://www.cnblogs.com/Leo_wl/p/5863066.html
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[] { 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"); 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