.net Dapper 学习系列(2) ---Dapper进阶
写在前面
在上一小节中,我们学习、实践和总结记录了Dapper的基础用法。而这一小节,我们继续深入的学习一下Dapper这个小型
ORM框架的其他用法。在这个实列中,我们会用到两个有关联的表。
前期准备
首先,还是沿用之前的的项目。库还是原来的DemoDb数据库。如还是不清楚的,可以看上一篇。
在DemoDb数据库新增产品表
//用户表
create table[sys_user](
[user_id] [nvarchar](36) primary key not null,
[u_id] [nvarchar](20) null,
[u_password] [nchar](50) null,
[gender] [nchar](1) null,
[user_name] [nvarchar](50) null,
[creation_time] [datetime] default(getdate()) null,
[status] [nvarchar](1) null,
)
//产品表
create table [sys_product](
[productid] [nvarchar](36) primary key not null,
[productname] [nvarchar](50) null,
[productDesc] [nvarchar](50) null,
[CreateTime] [datetime] defatul(getdate()) null,
[user_id] [nvarchar](36) null,
)
在Model 中添加 产品表的类
//用户
public class sys_user_sqlserver
{
[DisplayName("用户主键")]
public string user_id { get; set; }
[DisplayName("登录名称")]
public string u_id { get; set; }
[DisplayName("登录密码")]
public string u_password { get; set; }
[DisplayName("性别")]
public string gender { get; set; }
[DisplayName("姓名")]
public string user_name { get; set; }
[DisplayName("创建时间")]
public string creation_time { get; set; }
[DisplayName("状态")]
public string status { get; set; }
}
//产品
public class sys_product_sqlserver
{
[DisplayName("产品主键")]
public string productid { get; set; }
[DisplayName("产品名称")]
public string productname { get; set; }
[DisplayName("产品描述")]
public string productDesc { get; set; }
[DisplayName("用户主键")]
public string user_id { get; set; }
//public sys_user_sqlserver userown { get; set; }
[DisplayName("创建时间")]
public DateTime CreateTime { get; set; }
}
Dapper 单表批量添加
using System.Configuration;//ConfigurationManager
using Dapper;//SqlMapper
using System.Data;//IDbConnection
using System.Data.SqlClient; //SqlConnection
using Newtonsoft.Json;//
using MySql.Data.MySqlClient;
using Newtonsoft.Json.Linq;
using System.Diagnostics;//mysql
/*连接字符串*/
private static string connstr_sqlserver = ConfigurationManager.ConnectionStrings["lc"].ToString();
/// <summary>
/// 单表批量添加
/// </summary>
/// <param name="user">泛型集合</param>
/// <returns>成功返回1,失败返回0</returns>
[HttpPost]
public int Add_Many(List<sys_user_sqlserver> user)
{
/*模拟数据*/
user = new List<sys_user_sqlserver> {
new sys_user_sqlserver { user_id =Guid.NewGuid().ToString(), u_id = "Admin", u_password = "admin001", gender = "m", user_name = "管理员", status = "y" },
new sys_user_sqlserver { user_id =Guid.NewGuid().ToString(), u_id = "User", u_password = "user001", gender = "m", user_name = "用户", status = "y" },
new sys_user_sqlserver { user_id =Guid.NewGuid().ToString(), u_id = "ZhangSan", u_password = "zhangsan001", gender = "m", user_name = "张三", status = "y" },
new sys_user_sqlserver { user_id =Guid.NewGuid().ToString(), u_id = "LiSi", u_password = "LiSi001", gender = "w", user_name = "李思", status = "y" },
new sys_user_sqlserver { user_id =Guid.NewGuid().ToString(), u_id = "ZhaoQian", u_password = "zhaoqiao001", gender = "w", user_name = "赵钱", status = "y" },
};
/*声明结果*/
int result = 0;
/*连接Sqlserver 数据库*/
using (IDbConnection conn = new SqlConnection(connstr_sqlserver))
{
/*sql 语句*/
string sql_add = @"insert into sys_user(user_id,u_id,u_password,gender,user_name,status)";
sql_add += " values (newid(),@u_id,@u_password,@gender,@user_name,@status)";
/*执行Execute(参数1,参数2) 参数1:sql语句,参数2:(可以是一个对象也可以是一个泛型集合)*/
int results = conn.Execute(sql_add, user);
if (results > 0) { result = 1; }
}
/*成功返回1,失败返回0*/
return result;
}

在Dapper 多表查询
/// <summary>
/// 多表查询
/// </summary>
/// <returns></returns>
[HttpGet]
public JsonResult ManyToOne()
{
using (IDbConnection conn = new SqlConnection(connstr_sqlserver))
{
string sql = "select p.productid,p.productname,p.productDesc,u.user_name from sys_product p ";
sql += "join sys_user u on p.user_id=u.user_id";
#region 方式1 返回泛型
var product = conn.Query<sys_product_sqlserver, sys_user_sqlserver, sys_product_sqlserver>(sql,
(products, users) =>
{
products.userown = users; return products;
}, splitOn: "user_name");
#endregion
#region 方式2 默认返回 dynamic
////var product = conn.Query(sql);
#endregion
return Json(product, JsonRequestBehavior.AllowGet);
}
}

在Dapper 调用存储过程
/*创建存储过程*/
create proc proc_queryUser
@user_id varchar(50)
as
begin
select * from sys_user where user_id=@user_id;
end
/*在程序中使用Dapper调用存储过程*/
/// <summary>
/// Dapper 调用存储过程
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public JsonResult Get_Proc(string id)
{
/*模型接收数据*/
stirng Id="7384A533-44FA-4358-8171-0162F4950292";
/*打开数据库连接*/
using (IDbConnection conn = new SqlConnection(connstr_sqlserver))
{
#region 方法1
//var result = conn.Query<sys_user_sqlserver>("proc_queryUser",
//new { user_id = id }, null, true, null,
//CommandType.StoredProcedure);
#endregion
#region 方法2
/*调用存储过程*/
var result = conn.Query<sys_user_sqlserver>("proc_queryUser",
new { user_id = id },
commandType: CommandType.StoredProcedure);
#endregion
/*返回结果集*/
return Json(result, JsonRequestBehavior.AllowGet);
}
}

在Dapper 使用QueryMultiple进行多表查询
错误写法:
public SqlMapper.GridReader Get_Readers_Data()
{
using (IDbConnection conn = new SqlConnection(connstr_sqlserver))
{
string sql = @"select * from sys_user;select * from sys_product;";
#region 方式1 QueryMultiple(sql语句);
var data = conn.QueryMultiple(sql);
#endregion
#region 方式2 QueryMultiple(连接字符串,sql语句);
//var data = SqlMapper.QueryMultiple(conn, sql);
#endregion
return data;
}
}
public JsonResult Get_All_Data()
{
var all = Get_Reader_Data();
var users = all.Read<sys_user_sqlserver>().ToList();
var products = all.Read<sys_product_sqlserver>().ToList();
Dictionary<string, object> dic = new Dictionary<string, object>();
dic.Add("user",users);
dic.Add("product",products);
return Json(dic, JsonRequestBehavior.AllowGet);
}
这时我们运行程序,会发现出现如图的错误。错误:阅读器关闭时尝试调用 FieldCount无效[解决方案]。

分析错误原因:
*.首先:使用using{}作用域之后,连接会自动关闭。
*.其次:使用的是DataSet 读取数据库是它会把读到的数据数据存放在本地内存中。但是,Reader则不会。
*.最后:它只是指向了数据,连接关闭后用reader读取数据当然无法实现。
所以,正确的做法是,去除Using{}作用域。
//正确做法
public SqlMapper.GridReader Get_Readers_Data()
{
/*打开数据库连接*/
IDbConnection conn = new SqlConnection(connstr_sqlserver);
/*sql语句*/
string sql = @"select * from sys_product; select * from sys_user";
#region 方式1 QueryMultiple(sql语句);
/*调用 QueryMultiple 返回过个结果集 */
var data = conn.QueryMultiple(sql);
#endregion
#region 方式2 QueryMultiple(连接字符串,sql语句);
//var data = SqlMapper.QueryMultiple(conn, sql);
#endregion
return data;
}
public JsonResult Get_All_Data()
{
var all = Get_Reader_Data();
var users = all.Read<sys_user_sqlserver>().ToList();
var products = all.Read<sys_product_sqlserver>().ToList();
Dictionary<string, object> dic = new Dictionary<string, object>();
dic.Add("user",users);
dic.Add("product",products);
return Json(dic, JsonRequestBehavior.AllowGet);
}
注意:
这里查询表顺序和读取表的顺序必须要一样。如果两者顺序不一样是没有数据返回的。
会出现返回值都是NULL的情况。而造成这样的原因是Reader 是按照查询的结果依次读取显示的。
所以,查询表顺序和读取表的顺序必须一样。否则就会出现类似于下图的情况。
如图所示:


在Dapper 使用事务进行多表添加
[HttpPost]
public int Get_Tran_Add(List<sys_product_sqlserver> product, sys_user_sqlserver user)
{
int result;
/*连接sqlserver 数据库*/
using (IDbConnection conn = new SqlConnection(connstr_sqlserver))
{
/*模拟数据*/
var ID = Guid.NewGuid();
user = new sys_user_sqlserver { user_id = ID.ToString(), u_id = "admin", u_password = "admin", gender = "m", user_name = "管理员", status = "y" };
product = new List<sys_product_sqlserver> {
new sys_product_sqlserver{productid=Guid.NewGuid().ToString(),productname="产品1",productDesc="产品描述1",user_id=ID.ToString()},
new sys_product_sqlserver{productid=Guid.NewGuid().ToString(),productname="产品2",productDesc="产品描述2",user_id=ID.ToString()},
new sys_product_sqlserver{productid=Guid.NewGuid().ToString(),productname="产品3",productDesc="产品描述3",user_id=ID.ToString()},
new sys_product_sqlserver{productid=Guid.NewGuid().ToString(),productname="产品4",productDesc="产品描述4",user_id=ID.ToString()},
new sys_product_sqlserver{productid=Guid.NewGuid().ToString(),productname="产品5",productDesc="产品描述5",user_id=ID.ToString()}
};
/*sql语句*/
string sql1 = @"insert into sys_user(user_id,u_id,u_password,gender,user_name,status)";
sql1 += " values (@user_id,@u_id,@u_password,@gender,@user_name,@status)";
string sql2 = @"insert into sys_product(productname,productDesc,user_id)";
sql2 += " values (@productname,@productDesc,@user_id)";
/*注意:要记得打开连接。否则会报错:无效操作。连接被关闭。*/
conn.Open();
/*开始事务*/
IDbTransaction tran = conn.BeginTransaction();
try
{
/*执行事务*/
var resultOne = conn.Execute(sql1, user, tran);
var resultTwo = conn.Execute(sql2, product, tran);
/*提交事务*/
tran.Commit();
result = 1;
}
catch (Exception)
{
/*回滚事务*/
tran.Rollback();
result = 0;
throw;
}
}
/*成功返回1,失败返回0*/
return result;
}
注意:
在使用事务的时候注意要加上dbConnection.Open(),因为在BeginTransaction时要求连接是打开的。
而在不使用事务的时候,简单的增删改查可以不用这一句,因为Execute方法中有Open。
否则会报错:无效操作。连接被关闭。

在Dapper 使用事务进行多表编辑
[HttpPost]
public int Get_Tran_Edit(List<sys_product_sqlserver> product, sys_user_sqlserver user)
{
int result;
/*连接sqlserver 数据库*/
using (IDbConnection conn = new SqlConnection(connstr_sqlserver))
{
//注意要加上dbConnection.Open(),因为在BeginTransaction时要求连接是打开的。而
//在不使用事务的时候,简单的增删改查可以不用这一句,因为Execute方法中有Open。否则会报错:无效操作。连接被关闭。
/*模拟接收数据*/
var ID = "EF2D72DD-5D45-482A-A26E-FF3AF3A39DE9";
user = new sys_user_sqlserver { user_id = ID, u_id = "admin1", u_password = "admin1", gender = "w", user_name = "管理员1", status = "n" };
product = new List<sys_product_sqlserver> {
new sys_product_sqlserver{productid="04245342-1855-4171-B408-2A04FCF5696B",productname="产品11",productDesc="产品描述11",user_id=ID},
new sys_product_sqlserver{productid="C268A332-38B5-49E9-AFC1-E6E9EB62D2A2",productname="产品21",productDesc="产品描述21",user_id=ID},
new sys_product_sqlserver{productid="823E4F43-31FC-4355-BA12-925AC7704340",productname="产品31",productDesc="产品描述31",user_id=ID},
new sys_product_sqlserver{productid="93E8829E-5ED1-45BF-B979-E22405D092D1",productname="产品41",productDesc="产品描述41",user_id=ID},
new sys_product_sqlserver{productid="6EF52CA5-AB9B-41E1-B335-16C86F2A445C",productname="产品51",productDesc="产品描述51",user_id=ID}
};
/*sql语句*/
string sql_add = @"update sys_user set u_id=@u_id,u_password=@u_password,gender=@gender,";
sql_add += "user_name=@user_name,status=@status where user_id=@user_id";
string sql = @"update sys_product set productname=@productname,productDesc=@productDesc,user_id=@user_id";
sql += " where productid=@productid";
/*注意:要记得打开连接。否则会报错:无效操作。连接被关闭。*/
conn.Open();
/*开始事务*/
IDbTransaction tran = conn.BeginTransaction();
try
{
/*执行事务*/
var resultOne = conn.Execute(sql_add, user, tran);
var resultTwo = conn.Execute(sql, product, tran);
/*提交事务*/
tran.Commit();
result = 1;
}
catch (Exception)
{
/*事务回滚*/
tran.Rollback();
result = 0;
throw;
}
}
/*6.成功返回结果1,失败返回结果0*/
return result;
}

在Dapper 使用事务进行多表删除
[HttpPost]
public int Get_Tran_Del()
{
int result;
/*连接sqlserver 数据库*/
using (IDbConnection conn = new SqlConnection(connstr_sqlserver))
{
//注意要加上dbConnection.Open(),因为在BeginTransaction时要求连接是打开的。而
//在不使用事务的时候,简单的增删改查可以不用这一句,因为Execute方法中有Open。否则会报错:无效操作。连接被关闭。
/*注意:要记得打开连接。否则会报错:无效操作。连接被关闭。*/
conn.Open();
/*开始事务*/
IDbTransaction transaction = conn.BeginTransaction();
try
{
/*执行事务*/
string query1 = "delete from sys_user where user_id = @user_id";
string query2 = "delete from sys_product where user_id = @user_id";
conn.Execute(query1, new { user_id = "f2ffed38-9f43-4088-80af-138990a76e60" }, transaction, null, null);
conn.Execute(query2, new { user_id = "f2ffed38-9f43-4088-80af-138990a76e60" }, transaction, null, null);
/*提交事务*/
transaction.Commit();
result = 1;
}
catch (Exception ex)
{
/*回滚事务*/
//出现异常,事务Rollback
transaction.Rollback();
result = 0;
throw new Exception(ex.Message);
}
}
return result;
}

总结
好记性不如‘烂笔头’。到目前为止,总结了Dapper 常用的一些操作。如果项目小,又对性能有较高要求的话,可以选择Dapper 这个小型的ORM框架进行项目的快速开发。
.net Dapper 学习系列(2) ---Dapper进阶的更多相关文章
- .net Dapper 学习系列(1) ---Dapper入门
目录 写在前面 为什么选择Dapper 在项目中安装Dapper 在项目中使用Dapper 在项目中使用Dapper 进行单表增删改数据操作 总结 写在前面 Dapper 是一款轻量级ORM架构.为解 ...
- Dapper学习(四)之Dapper Plus的大数据量的操作
这篇文章主要讲 Dapper Plus,它使用用来操作大数量的一些操作的.比如插入1000条,或者10000条的数据时,再使用Dapper的Execute方法,就会比较慢了.这时候,可以使用Dappe ...
- Net系列框架-Dapper+简单三层架构
Net系列框架-Dapper+简单三层架构 工作将近6年多了,工作中也陆陆续续学习和搭建了不少的框架,后续将按由浅入深的方式,整理出一些框架源码,所有框架源码本人都亲自调试通过,如果有问题,欢迎联系我 ...
- Net系列框架-Dapper+AutoFac 基于接口
Net系列框架-Dapper+AutoFac 基于接口 工作将近6年多了,工作中也陆陆续续学习和搭建了不少的框架,后续将按由浅入深的方式,整理出一些框架源码,所有框架源码本人都亲自调试通过,如果有问题 ...
- dapper 学习
上一篇, 提到Query<Test>查询的时候, 如果Test中包含自定义class, Dapper不会给自定义class完成映射, 而是直接给null, 其实是可以实现的, 答案就在下面 ...
- Dapper学习(三)之其他用法
这里说的其他用法,是指 Async,Buffered,Transaction,Stored Procedure. 1. 首先 dapper支持异步 ExecuteAsync, QueryAsync, ...
- Dapper学习(一)之Execute和Query
Dapper是一个用于.NET的简单的对象映射,并且在速度上有着轻ORM之王的称号. Dapper扩展IDbConnection,提供有用的扩展方法来查询数据库. 那么Dapper是怎样工作的呢? 总 ...
- .NET Core 学习资料精选:进阶
.NET 3.0 这个月就要正式发布了,对于前一篇博文<.NET Core 学习资料精选:入门>大家学的可还开心?这是本系列的第二篇文章:进阶篇,喜欢的园友速度学起来啊. 对于还在使用传统 ...
- dotnet学习系列
这里整理下之前关于dotnet方面的文章索引. 一.dotnet core 系列 dotnet core 微服务教程 asp.net core 系列之并发冲突 asp.net core 系列之中间件进 ...
随机推荐
- tomcat 启动中文乱码
1.情景展示 从Apache官网下载的tomcat,启动后中文日志信息显示乱码. 启动startup.bat后 2.原因分析 通过修改日志输出的字符集来解决. 3.解决方案 tomcat安装目 ...
- <每日 1 OJ> -内存文件系统
蛮有意思的,主要考查链表和树结构的知识. 代码如下: ************************************************************************* ...
- 自顶向下深入分析Netty(七)--ChannelPipeline和ChannelHandler总述
自顶向下深入分析Netty(七)--ChannelPipeline和ChannelHandler总述 自顶向下深入分析Netty(七)--ChannelPipeline源码实现 自顶向下深入分析Net ...
- 深度学习最全优化方法总结比较及在tensorflow实现
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u010899985/article/d ...
- Server Tomcat v8.5 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
Server Tomcat v9.0 Server at localhost was unable to start within 45 seconds. If the server requires ...
- SpringBoot项目中普通类获取http相关的类(request/response/session)
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import ...
- HandlerMethodArgumentResolver的抽象實現AbstractNamedValueMethodArgumentResolver下的子类
Annotation-based argument resolution 部分2 org.springframework.web.servlet.mvc.method.annotation.Reque ...
- tensorflow 13:多gpu 并行训练
多卡训练模式: 进行深度学习模型训练的时候,一般使用GPU来进行加速,当训练样本只有百万级别的时候,单卡GPU通常就能满足我们的需求,但是当训练样本量达到上千万,上亿级别之后,单卡训练耗时很长,这个时 ...
- centos7.6使用 supervisor 对filebeat7.3.1进程进行管理
centos7.6使用 supervisor 对filebeat7.3.1进程进行管理 Supervisor 是一个 Python 开发的 client/server 系统,可以管理和监控类 UNIX ...
- Numa 常用命令
1. 查看numa相关信息,包括每个node内存大小,每个node中的逻辑cpu: numactl --hardware