Dapper上手
Dapper 特点: 小型ORM:Dapper是一个轻型的ORM类。源码代码量少,编译后就40K的一个很小的Dll.; 速度快:Dapper的速度接近与IDataReader,取列表的数据超过了DataTable; 支持多数据库:Dapper支持Mysql,SqlLite,Mssql,Oracle等一系列的数据库; 灵活性高:支持一对多 多对多的关系,无XML无属性。代码以前怎么写现在还怎么写; 性能高:通过Emit反射IDataReader的序列队列,来快速的得到和产生对象; 支持.net版本:支持多个版本.Net,如:.Net Framework和.Net Core; 可扩展性强:语法简单,并且无须迁就数据库的设计。
二、常用方法
1.准备
安装
本文使用的是.Net6版本,通过NuGet安装相应版本的Dapper和MySql.Data:
dotnet add package Dapper --version 2.0.123
dotnet add package MySql.Data --version 8.0.32.1
创建表格,这里使用的是MySql5.5:
/* 创建表 */
CREATE TABLE `assignment` (
`assignmentNo` decimal(4,0) NOT NULL,
`empno` varchar(10) DEFAULT NULL,
`content` varchar(50) DEFAULT NULL,
PRIMARY KEY (`assignmentNo`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `dept` (
`deptno` decimal(4,0) NOT NULL,
`deptname` varchar(20) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `emp` (
`empno` decimal(4,0) NOT NULL,
`ename` varchar(10) DEFAULT NULL,
`job` varchar(20) DEFAULT NULL,
`hiredate` datetime DEFAULT NULL,
`sal` decimal(10,0) DEFAULT NULL,
`deptno` decimal(4,0) DEFAULT NULL,
PRIMARY KEY (`empno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Dapper使用三个步骤: 创建一个IDbConnection接口对象; 编写一个查询SQL来执行CRUD操作; 将查询SQL作为Execute方法的参数传递。
2. Execute
Execute 是一个可以从 IDbConnection 类型的任意对象调用的扩展方法,它可以执行一个或多个命令并返回受影响的行数。
参数:
参数含义sql要执行的命令文本param命令参数(默认为null)transaction需要使用的事务(默认为null)commandTimeout命令执行超时时间(默认为null)commandType命令类型(默认为null)
代码如下(示例):
INSERT语句
执行单次INSERT语句
string sql = "INSERT INTO emp(empno,ename,job,hiredate,sal) Values (@empno,@ename,@job,@hiredate,@sal);";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql, new { empno = 7369, ename = "SMITH", job = "SALESMAN", hiredate = "2022-4-1", sal = 9000 });
}
执行多次INSERT语句
string sql = "INSERT INTO emp(empno,ename,job,hiredate,sal) Values (@empno,@ename,@job,@hiredate,@sal);";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql,
new[]
{
new { empno = 7779 , ename = "宋江",job= "SALESMAN", hiredate="2022-5-1",sal =9000 },
new { empno = 7780 , ename = "李逵",job= "SALESMAN", hiredate="2022-6-1",sal =9000 },
new { empno = 7781 , ename = "关胜",job= "SALESMAN", hiredate="2022-6-1",sal =9000 },
new { empno = 7782 , ename = "白日鼠",job= "SALESMAN", hiredate="2022-6-1",sal =9000 },
});
}
UPDATE语句
执行单次UPDATE语句
string sql = "UPDATE emp SET ename =@ename WHERE empno =@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql, new { empno = 7369, ename = "yulan" });
}
执行多次UPDATE语句
string sql = "UPDATE emp SET ename =@ename WHERE empno =@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql,
new[]
{
new { empno =7369,ename ="卢俊义" },
new { empno =7777,ename ="林冲"}
});
}
DELETE语句
执行单次DELETE语句
string sql = "DELETE FROM emp WHERE empno =@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql, new { empno = 7780 });
}
执行多次DELETE语句
string sql = "DELETE FROM emp WHERE empno =@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql,
new[]
{
new{ empno = 7781 },
new{ empno = 7782 }
});
}
有参存储过程
执行单次存储过程
string sql = "sp_GetEmpInfo";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql, new { param_empno = 7777, param_ename = "卢俊义123" }, commandType: CommandType.StoredProcedure);
}
执行多次存储过程
string sql = "sp_GetEmpInfo";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql,
new[]
{
new { param_empno = 7777, param_ename = "林冲" },
new { param_empno = 7778, param_ename = "宋江" },
},
commandType: CommandType.StoredProcedure);
}
2.Query
Query是一个可以从IDbConnection类型的任意对象调用的扩展方法,它可以执行查询并映射结果。
参数:
参数含义sql要执行的查询param查询参数(默认为null)transaction需要使用的事务(默认为null)buffered是否从缓冲读取查询结果(默认为true)commandTimeout命令执行超时时间(默认为null)commandType命令类型(默认为null)
代码如下(示例):
查询匿名类型
string sql = "SELECT * FROM emp";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emps = connection.Query(sql).ToList();
}
查询强类型
string sql = "SELECT * FROM emp";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emps = connection.Query(sql).ToList();
}
查询多映射(一对一)
string sql = "SELECT * FROM emp INNER JOIN dept ON emp.deptno = dept.deptno;";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emps = connection.Query(sql,
(emps, dept) =>
{
emps.deptInfo = dept;
return emps;
},
splitOn: "deptno").Distinct().ToList();
}
查询多映射(一对多)
string sql = "SELECT * FROM emp INNER JOIN assignment ON emp.empno = assignment.empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var empAssignment = new Dictionary();
var emps = connection.Query(sql,
(emp, assignment) =>
{
Emp empEntity;
if (!empAssignment.TryGetValue(emp.empno, out empEntity))
{
empEntity = emp;
empEntity.assignments = new List();
empAssignment.Add(empEntity.empno, empEntity);
}
empEntity.assignments.Add(assignment);
return empEntity;
},splitOn: "empno").Distinct().ToList();
}
3.QueryFirst
QueryFirst是一个可以从IDbConnection类型的任意对象调用的扩展方法,它可以执行查询并映射第一个结果。
参数:
参数含义sql要执行的查询param查询参数(默认为null)transaction需要使用的事务(默认为null)commandTimeout命令执行超时时间(默认为null)commandType命令类型(默认为null)
First, Single和Default比较
方法查询没有结果时有一条数据有多条数据First抛异常当前项第一项Single抛异常当前项抛异常FirstOrDefault默认值当前项第一项SingleOrDefault默认值当前项抛异常
查询匿名类型
string sql = "SELECT * FROM emp WHERE empno=@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emp = connection.QueryFirst(sql, new { empno = 7777 });
}
查询强类型
string sql = "SELECT * FROM emp WHERE empno=@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emp = connection.QueryFirst(sql, new { empno = 7777 });
}
4.QueryFirstOrDefault
QueryFirstOrDefault是一个可以从IDbConnection类型的任意对象调用的扩展方法,它可以执行查询并映射第一个结果,如果序列不包含任何元素则为默认值。
参数:
参数含义sql要执行的查询param查询参数(默认为null)transaction需要使用的事务(默认为null)commandTimeout命令执行超时时间(默认为null)commandType命令类型(默认为null)
First, Single和Default比较
方法查询没有结果时有一条数据有多条数据First抛异常当前项第一项Single抛异常当前项抛异常FirstOrDefault默认值当前项第一项SingleOrDefault默认值当前项抛异常
查询匿名类型
string sql = "SELECT * FROM emp WHERE empno=@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emp = connection.QueryFirstOrDefault(sql, new { empno = 7777 });
}
查询强类型
string sql = "SELECT * FROM emp WHERE empno=@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emp = connection.QueryFirstOrDefault(sql, new { empno = 7777 });
}
5.QuerySingle
QuerySingle是一个可以从IDbConnection类型的任意对象调用的扩展方法,它可以执行查询并映射第一个结果,如果序列中没有元素则会引发异常。
参数:
参数含义sql要执行的查询param查询参数(默认为null)transaction需要使用的事务(默认为null)commandTimeout命令执行超时时间(默认为null)commandType命令类型(默认为null)
查询匿名类型
string sql = "SELECT * FROM emp WHERE empno=@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emp = connection.QuerySingle(sql, new { empno = 7777 });
}
查询强类型
string sql = "SELECT * FROM emp WHERE empno=@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emp = connection.QuerySingle(sql, new { empno = 7777 });
}
6.QuerySingleOrDefault
QuerySingleOrDefault是一个可以从IDbConnection类型的任意对象调用的扩展方法,它可以执行查询并映射第一个结果,如果序列为空则为默认值。如果序列中有多个元素,则此方法将引发异常。
参数:
参数含义sql要执行的查询param查询参数(默认为null)transaction需要使用的事务(默认为null)commandTimeout命令执行超时时间(默认为null)commandType命令类型(默认为null)
查询匿名类型
string sql = "SELECT * FROM emp WHERE empno=@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emp = connection.QuerySingleOrDefault(sql, new { empno = 7777 });
}
查询强类型
string sql = "SELECT * FROM emp WHERE empno=@empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emp = connection.QuerySingleOrDefault(sql, new { empno = 7777 });
}
7.QueryMultiple
QueryMultiple是一个可以从IDbConnection类型的任意对象调用的扩展方法,它可以在相同的命令和映射结果中执行多个查询。
参数:
参数含义sql要执行的查询param查询参数(默认为null)transaction需要使用的事务(默认为null)commandTimeout命令执行超时时间(默认为null)commandType命令类型(默认为null)
QueryMultiple方法
string sql = "SELECT * FROM emp WHERE empno =@empno;SELECT * FROM assignment WHERE assignmentNo =@assignmentNo";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
using (var multi = connection.QueryMultiple(sql, new { empno = 7777, assignmentNo=1 }))
{
var emps = multi.Read().First();
var assignments = multi.Read().ToList();
}
}
三、参数
1.匿名类型参数
Dapper通过支持匿名类型使其可以简单、安全(SQL注入)的使用参数。
单次执行
string sql = "sp_GetEmpInfo";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql, new { param_empno = 7777, param_ename = "卢俊义007" }, commandType: CommandType.StoredProcedure);
}
多次执行
string sql = "sp_GetEmpInfo";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql,
new[]
{
new { param_empno = 7777, param_ename = "林冲" },
new { param_empno = 7778, param_ename = "宋江" },
},
commandType: CommandType.StoredProcedure);
}
2.动态类型参数
在Dapper方法中创建并使用参数。
单次执行
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
DynamicParameters parameter = new DynamicParameters();
parameter.Add("@param_empno", 7777, DbType.Decimal, ParameterDirection.Input);
parameter.Add("@param_ename", "555", DbType.String, ParameterDirection.Input);
parameter.Add("@result_count", dbType: DbType.Int32, direction: ParameterDirection.Output);
connection.Execute("sp_ChangeEmpInfo", parameter, commandType: CommandType.StoredProcedure);
int rowCount = parameter.Get("@result_count");
}
多次执行
var sql = "sp_ChangeEmpInfo";
var parameters = new List();
for (var i = 0; i < 3; i++)
{
var p = new DynamicParameters();
p.Add("@param_empno", 7777+i, DbType.Int32, ParameterDirection.Input);
p.Add("@param_ename", "卢俊义" + (i + 1), DbType.String, ParameterDirection.Input);
p.Add("@result_count", dbType: DbType.Int32, direction: ParameterDirection.Output);
parameters.Add(p);
}
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
connection.Execute(sql, parameters, commandType: CommandType.StoredProcedure);
int rowCount = parameters.Sum(x => x.Get("@result_count"));
}
3.列表类型参数
Dapper允许您使用列表在IN子句中指定多个参数。
var sql = "SELECT * FROM emp WHERE empno in @empno";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
DynamicParameters parameter = new DynamicParameters();
parameter.Add("@param_empno", 7777, DbType.Decimal, ParameterDirection.Input);
parameter.Add("@param_ename", "555", DbType.String, ParameterDirection.Input);
parameter.Add("@result_count", dbType: DbType.Int32, direction: ParameterDirection.Output);
var emps = connection.Query(sql, new { empno = new[] {7777,7778 } }).ToList();
}
4.字符串类型参数
var sql = "SELECT * FROM emp WHERE ename = @ename";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emps = connection.Query(sql,
new { ename = new DbString { Value = "卢俊义", IsFixedLength = false, Length = 9, IsAnsi = true } }).ToList();
}
四、异步
Dapper还使用了Async(异步)方法扩展了IDbConnection接口: ExecuteAsync QueryAsync QueryFirstAsync QueryFirstOrDefaultAsync QuerySingleAsync QuerySingleOrDefaultAsync QueryMultipleAsync
示例:
string sql = "INSERT INTO emp(empno,ename,job,hiredate,sal) Values (@empno,@ename,@job,@hiredate,@sal);";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
// 异步
var affectedRows = connection.ExecuteAsync(sql, new { empno = 7369, ename = "SMITH", job = "SALESMAN", hiredate = "2022-4-1", sal = 9000 });
}
五、Dapper支持事务和范围事务
1.事务
从连接开始一个新事务,并将其传递给事务可选参数。
示例:
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
DynamicParameters parameter = new DynamicParameters();
parameter.Add("@param_empno", 7777, DbType.Decimal, ParameterDirection.Input);
parameter.Add("@param_ename", "555", DbType.String, ParameterDirection.Input);
parameter.Add("@result_count", dbType: DbType.Int32, direction: ParameterDirection.Output);
connection.Execute("sp_ChangeEmpInfo", parameter, commandType: CommandType.StoredProcedure, transaction: transaction);
int rowCount = parameter.Get("@result_count");
transaction.Commit();
}
}
2.范围事务
在开始连接之前开始一个新的范围事务。
示例:
using (var transaction = new TransactionScope())
{
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
DynamicParameters parameter = new DynamicParameters();
parameter.Add("@param_empno", 7777, DbType.Decimal, ParameterDirection.Input);
parameter.Add("@param_ename", "555", DbType.String, ParameterDirection.Input);
parameter.Add("@result_count", dbType: DbType.Int32, direction: ParameterDirection.Output);
connection.Execute("sp_ChangeEmpInfo", parameter, commandType: CommandType.StoredProcedure);
int rowCount = parameter.Get("@result_count");
}
transaction.Complete();
}
六、缓冲
缓冲查询对于一个非常大的查询来减少内存使用情况有一定作用。
string sql = "SELECT * FROM emp";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var emps = connection.Query(sql, buffered: false).ToList();
}
七、存储过程
执行一次存储过程
string sql = "sp_GetEmpInfo";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql, new { param_empno = 7777, param_ename = "卢俊义123" }, commandType: CommandType.StoredProcedure);
}
执行多次存储过程,为参数数组列表中的每个对象执行一次
string sql = "sp_GetEmpInfo";
using (var connection = BaseRepository.GetMySqlConnection())
{
connection.Open();
var affectedRows = connection.Execute(sql,
new[]
{
new { param_empno = 7777, param_ename = "林冲" },
new { param_empno = 7778, param_ename = "宋江" },
},
commandType: CommandType.StoredProcedure);
}
代码示例下载
总结
以上就是在.net6快速使用Dapper,本文从Dapper的方法使用、参数、事务和存储过程等方法,提供Dapper框架的代码使用示例使我们快速便捷地使用该ROM框架。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix