Dapper的异步方式使用学习

Dapper异步使用学习

Dapper已经赢得了C#轻量级ORM的王者称号,但却被很多人认为是一款用于.Net环境的简单的对象映射器。当人们希望自己编写具有最佳性能的SQL查询时,他们会更喜欢Dapper。Dapper是100%安全的!你可以像往常一样使用参数化查询,不用担心被SQL注入的问题,此外Dapper还支持事务操作,第三方扩展的Dapper. Plus 还支持批量操作!而且已经支持异步了,最近我就尝试了使用Dapper的异步方法来操作数据库,所以在此做个分享,也加深一遍理解。
尤其是对三表Join操作的splitOn参数的理解,以及事务操作的使用,说实话,文档里有很多细节并未详细说明,只能靠你自己去实践,模拟业务场景去实验是最佳的学习方式,很多技术内部细节都能靠尝试和实验反推出来。
Dapper官方主页:

1. 数据库创建表

学习Dapper首先要先准备好一个数据库,这里我选择MySQL,Mysql比较常用,基本上生产环境普遍都是Mysql,我也曾尝试安装过Sql Server 2017 但是实在是太大了,作为开发者,它远不如Mysql更轻量,更易安装使用。先建一个数据库,创建三张表,角色表,用户表,部门表,三张表有关联关系,SQL语句如下:

-- 部门表
CREATE TABLE `Departments`  (
  `ID` int(0) NOT NULL AUTO_INCREMENT,
  `DepartmentName` varchar(50) 
  `PDepartmentID` int(0) NOT NULL,
  PRIMARY KEY (`ID`) USING BTREE
)

-- 角色表
CREATE TABLE `Roles`  (
  `ID` int(0) NOT NULL AUTO_INCREMENT,
  `RoleName` varchar(20)
  PRIMARY KEY (`ID`) USING BTREE
)

-- 用户表
CREATE TABLE `Users`  (
  `ID` int(0) NOT NULL AUTO_INCREMENT,
  `DepartmentID` int(0) DEFAULT NULL,
  `Name` varchar(50) 
  `Password` varchar(50)
  `RoleID` int(0) DEFAULT NULL,
  `UserName` varchar(50)
  PRIMARY KEY (`ID`) USING BTREE
) 
2. 实体类创建

使用过ORM框架的童鞋们都知道,如果使用ORM,必要条件就是要创建与表各字段关系对应的实体类,Object-Relationl Mapping,它的作用就是在关系型数据库和对象之间作一个映射。

/// <summary>
/// 角色
/// </summary>
public class Roles
{
	public int ID { get; set; }
	public string RoleName { get; set; }
}

/// <summary>
/// 部门
/// </summary>
public class Departments
{
	public int ID { get; set; }
	public string DepartmentName { get; set; }
	public int PDepartmentID { get; set; }
}

/// <summary>
/// 用户
/// </summary>
public class Users
{
	public int ID { get; set; }
	public int DepartmentID { get; set; }
	public string Name { get; set; }
	public string Password { get; set; }
	public int RoleID { get; set; }
	public string UserName { get; set; }
}

/// <summary>
/// 用户角色综合
/// </summary>
public class UsersAndRole
{
	public int ID { get; set; }
	public string Name { get; set; }
	public string Password { get; set; }
	public string UserName { get; set; }
	public string RoleName { get; set; }
	public string DepartmentName { get; set; }
	public Roles Role { get; set; }
}
3. 执行插入/修改/删除

插入,删除和修改操作,基本相同,所以这里只写了插入操作的实例代码。

// 插入单个对象
public static async Task<int> InsertRoleAsync()
{
	using (IDbConnection connection = new MySqlConnection(connectionString))
	{
		return await connection.ExecuteAsync("insert into Roles(RoleName) values(@RoleName)", 
		new Roles()
		{
			RoleName = "管理员"
		});
	}
}

// 插入多个对象
public static async Task<int> InsertBatchRoleAsync()
{
	using (IDbConnection connection = new MySqlConnection(connectionString))
	{
		return await connection.ExecuteAsync("insert into Roles(RoleName) values(@RoleName)", 
		new List<Roles>()
		{
			new Roles(){ RoleName="a"},
			new Roles(){ RoleName="b"},
			new Roles(){ RoleName="c"},
		});
	}
}
4. 基本查询操作

基本查询语句操作包括,无参数查询,有参数查询,In语句查询,及 多语句执行查询,这里均采用异步的方法。

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

/// <summary>
/// 查询指定数据
/// </summary>
/// <param name="person"></param>
/// <returns></returns>
public static Roles QueryRolesByRoleName(string roleName)
{
	using (IDbConnection connection = new MySqlConnection(connectionString))
	{
		return connection.QueryAsync<Roles>("select * from Roles where RoleName=@RoleName", 
			new { RoleName= roleName }).Result.SingleOrDefault();
	}
}

/// <summary>
/// In语句操作
/// </summary>
public static List<Roles> QueryIn()
{
	using (IDbConnection connection = new MySqlConnection(connectionString))
	{
		var sql = "select * from Roles where id in @ids";
		return connection.QueryAsync<Roles>(sql, new { ids = new int[2] { 1, 2 }, }).Result.ToList();
	}
}

/// <summary>
/// 多语句操作
/// </summary>
public static void QueryUsersAndRolesMultiple()
{
	using (IDbConnection connection = new MySqlConnection(connectionString))
	{
		var sql = "select * from Users; select * from Roles";
		var multiReader = connection.QueryMultiple(sql);
		var roleList = multiReader.Read<Roles>();
		var userList = multiReader.Read<Users>();
		Console.WriteLine(JsonConvert.SerializeObject(roleList));
		Console.WriteLine(JsonConvert.SerializeObject(userList));
		multiReader.Dispose();
	}
}

5. Join内联接查询

Join内联接查询,这个实例是我特意设计出来的,采用三个关联表Join联合查询出用户的详细数据,根据字段的顺序,我将splitOn分割参数设置为"Name"字段,因为只要在Name字段时才能查出所有字段的值,Dapper扫描字段是按照从右向左的顺序扫的,所以尽量选择字段顺序最开始的除了ID之外的字段作为分割参数。
记住SQL语句中字段的顺序:u.id as ID,Name,Password,UserName,RoleName,DepartmentName

/// <summary>
/// Join查询
/// </summary>
/// <param name="UserName"></param>
/// <returns></returns>
public static UsersAndRole QueryAsyncJoin(string  UserName)
{
	using (IDbConnection connection = new MySqlConnection(connectionString))
	{
		var sql = @"SELECT u.id as ID,Name,Password,UserName,RoleName,DepartmentName
					FROM Users u 
					Join Roles r on u.RoleID=r.ID  
					Join Departments d on u.DepartmentID=d.ID 
					WHERE u.UserName=@userName
					";
		var result = connection.QueryAsync<Roles, UsersAndRole, UsersAndRole>(sql,
		(role,urd) =>
		{
			urd.Role = role;
			return urd;
		},new { userName = UserName },
		splitOn: "Name");
		return (UsersAndRole)result.Result.FirstOrDefault();
	}
}

执行方法

var result = QueryAsyncJoin("大林");
Console.WriteLine(JsonConvert.SerializeObject(result));

详细讲解一下,为了方便展示,我将查询结果Json序列化了,方便观察,我们先看按Name字段分割时的运行结果截图,可以看到所有字段值都查询出来了
按Name字段分割
如果按Password字段分割呢?你看显然,Name值就空了
按Password字段
再看按UserName分割,然后发现Name,Password都空了,你看,规律就找到了吧。
按UserName分割

6. 事务操作

事务操作分为Dapper的内部事务方法,和.Net 基础库自带的事务方法。

/// <summary>
/// Dapper事务
/// </summary>
/// <returns></returns>
public static int TransactionDapper()
{
	int effaffectedRows = -1;
	using (IDbConnection connection = new MySqlConnection(connectionString))
	{
		connection.Open();
		using (var transaction = connection.BeginTransaction())
		{
			effaffectedRows = connection.Execute("insert into Roles(RoleName) values(@RoleName)", 
			new Roles()
			{
				RoleName = "管理员"
			}, transaction: transaction);

			transaction.Commit();
		}
	}
	return effaffectedRows;
}

/// <summary>
/// 系统事务
/// </summary>
/// <returns></returns>
public static int TransactionSystem()
{
	int effaffectedRows = -1;
	using (var transaction = new TransactionScope())
	{
		using (IDbConnection connection = new MySqlConnection(connectionString))
		{
			connection.Open();
			effaffectedRows = connection.Execute("insert into Roles(RoleName) values(@RoleName)", 
			new Roles()
			{
				RoleName = "管理员"
			});
		}
		transaction.Complete();
		return effaffectedRows;
	}
}
7. Dapper 官方文档链接

https://dapper-tutorial.net/dapper

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
博文地址: https://www.cnblogs.com/cl-blogs/p/10219126.html 简单栗子: [Test] public void 三表联表分页测试() { LockPers lpmodel = new LockPers() { Name = "%蛋蛋%", IsDel = false}; Users umodel = new Users() { UserName = "jiaojiao" }; SynNote snmodel = new SynNote() { Name = "%木头%" }; Expression<Func<LockPers, Users, SynNote, bool>> where = PredicateBuilder.WhereStart<LockPers, Users, SynNote>(); where = where.And((lpw, uw, sn) => lpw.Name.Contains(lpmodel.Name)); where = where.And((lpw, uw, sn) => lpw.IsDel == lpmodel.IsDel); where = where.And((lpw, uw, sn) => uw.UserName == umodel.UserName); where = where.And((lpw, uw, sn) => sn.Name.Contains(snmodel.Name)); DapperSqlMaker<LockPers, Users, SynNote> query = LockDapperUtilsqlite<LockPers, Users, SynNote> .Selec() .Column((lp, u, s) => // null) //查询所有字段 new { lp.Id, lp.InsertTime, lp.EditCount, lp.IsDel, u.UserName, s.Content, s.Name }) .FromJoin(JoinType.Left, (lpp, uu, snn) => uu.Id == lpp.UserId , JoinType.Inner, (lpp, uu, snn) => uu.Id == snn.UserId) .Where(where) .Order((lp, w, sn) => new { lp.EditCount, lp.Name, sn.Content }); var result = query.ExcuteSelect(); //1. 执行查询 WriteJson(result); // 打印查询结果 Tuple<StringBuilder, DynamicParameters> resultsqlparams = query.RawSqlParams(); WriteSqlParams(resultsqlparams); // 打印生成sql和参数 int page = 2, rows = 3, records; var result2 = query.LoadPagelt(page, rows, out records); //2. 分页查询 WriteJson(result2); // 查询结果 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值