轉自: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

