Dapper的异步方式使用学习

Dapper异步使用学习 Dapper已经赢得了C#轻量级ORM的王者称号,但却被很多人认为是一款用于.Net环境的简单的对象映射器。当人们希望自己编写具有最佳性能的SQL查询时,他们会更喜欢Dapper。

 

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

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

————————————————
版权声明:本文为CSDN博主「卷儿哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/DahlinSky/article/details/104766612

weinxin
我的微信
一个码农、工程狮、集能量和智慧于一身的、DIY高手、小伙伴er很多的、80后奶爸。
Igor
  • 版权声明: 发表于 2023-01-0212:43:00
  • 转载注明:http://blog.tsingmac.com/prolions/codelanguage/mscs/5570/
如何使用 Dapper 中的异步方法 C/C++/C#

如何使用 Dapper 中的异步方法

Dapper 是一个 容易上手,轻量级,灵活高效,开源的 迷你 ORM,由 Stack Overflow 团队的 Sam Saffron 出品,你可以利用 Dapper 简化数据访问并且支持高性能, ...
c# - 异步使用MySQL DB C/C++/C#

c# – 异步使用MySQL DB

C#异步读取MySQL数据库的问题解决。 我试图了解异步使用数据库。为此,我用一个表创建了简单的MySQL数据库,然后可以通过以下方式从中获取信息: public static void SyncRe...
有200万用户的宝塔面板安全吗? 网络安全

有200万用户的宝塔面板安全吗?

宝塔面板系统是一款非常好用的网站服务器管理控制面板,成千上万的站长们把网站都架构在宝塔面板之上,如果面板出现了严重漏洞,宝塔面板安全吗? 宝塔面板系统是一款非常好用的网站服务器管理控制面板,可以让大家...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: