写在前面


在上一小节中,我们学习、实践和总结记录了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进阶的更多相关文章

  1. .net Dapper 学习系列(1) ---Dapper入门

    目录 写在前面 为什么选择Dapper 在项目中安装Dapper 在项目中使用Dapper 在项目中使用Dapper 进行单表增删改数据操作 总结 写在前面 Dapper 是一款轻量级ORM架构.为解 ...

  2. Dapper学习(四)之Dapper Plus的大数据量的操作

    这篇文章主要讲 Dapper Plus,它使用用来操作大数量的一些操作的.比如插入1000条,或者10000条的数据时,再使用Dapper的Execute方法,就会比较慢了.这时候,可以使用Dappe ...

  3. Net系列框架-Dapper+简单三层架构

    Net系列框架-Dapper+简单三层架构 工作将近6年多了,工作中也陆陆续续学习和搭建了不少的框架,后续将按由浅入深的方式,整理出一些框架源码,所有框架源码本人都亲自调试通过,如果有问题,欢迎联系我 ...

  4. Net系列框架-Dapper+AutoFac 基于接口

    Net系列框架-Dapper+AutoFac 基于接口 工作将近6年多了,工作中也陆陆续续学习和搭建了不少的框架,后续将按由浅入深的方式,整理出一些框架源码,所有框架源码本人都亲自调试通过,如果有问题 ...

  5. dapper 学习

    上一篇, 提到Query<Test>查询的时候, 如果Test中包含自定义class, Dapper不会给自定义class完成映射, 而是直接给null, 其实是可以实现的, 答案就在下面 ...

  6. Dapper学习(三)之其他用法

    这里说的其他用法,是指 Async,Buffered,Transaction,Stored Procedure. 1. 首先 dapper支持异步 ExecuteAsync, QueryAsync, ...

  7. Dapper学习(一)之Execute和Query

    Dapper是一个用于.NET的简单的对象映射,并且在速度上有着轻ORM之王的称号. Dapper扩展IDbConnection,提供有用的扩展方法来查询数据库. 那么Dapper是怎样工作的呢? 总 ...

  8. .NET Core 学习资料精选:进阶

    .NET 3.0 这个月就要正式发布了,对于前一篇博文<.NET Core 学习资料精选:入门>大家学的可还开心?这是本系列的第二篇文章:进阶篇,喜欢的园友速度学起来啊. 对于还在使用传统 ...

  9. dotnet学习系列

    这里整理下之前关于dotnet方面的文章索引. 一.dotnet core 系列 dotnet core 微服务教程 asp.net core 系列之并发冲突 asp.net core 系列之中间件进 ...

随机推荐

  1. linux运维 技能 2018

    1.监控与日志 prometheus.grafana.zabbix ELK(elasticsearch logstash filebeat kibana) 2.容器类 harbor映像管理 docke ...

  2. [转]OpenTK学习笔记(1)-源码、官网地址

    OpenTK源码下载地址:https://github.com/opentk/opentk OpenTK使用Nuget安装命令:OpenTK:Install-Package OpenTK -Versi ...

  3. Spring 事务小结

    @Override@Transactionalpublic void add() { this.in();} public void in(){ NyOrder nyOrder=new NyOrder ...

  4. sklearn的基本使用

    https://cloud.tencent.com/developer/news/58202 简介 今天为大家介绍的是scikit-learn.sklearn是一个Python第三方提供的非常强力的机 ...

  5. 转 linux 添加PHP环境变量,/etc/profile 不生效,每次都要 source /etc/profile

    http://shanhuxueyuan.com/news/detail/46.html 执行php -v 提示未找到命令,这是因为没有将php路径添加到环境变量 方法一:直接运行命令export P ...

  6. PAT 甲级 1020 Tree Traversals (25分)(后序中序链表建树,求层序)***重点复习

    1020 Tree Traversals (25分)   Suppose that all the keys in a binary tree are distinct positive intege ...

  7. springboot docker 部署

    1.新建一个最简单的springboot项目 https://code.aliyun.com/859143303/hello-world.git 2.src/main/docker下新建Dockerf ...

  8. DockerFile语法【h】

    DockerFile在我理解就是可以将所需要构建镜像的功能.组件都天前配置好,然后直接生成一个Image,而不是先生成镜像,再通过修改容器的方法来生成最终需要的镜像.   镜像的定值实际上就是定值每一 ...

  9. .net桌面程序或者控制台程序使用NLog时的注意事项

    Nuget添加NLog 添加nlog.config文件,并选择属性->始终复制 不选择始终复制,编译后nlog.config是没有的. 具体使用: private static readonly ...

  10. web基础---->script标签的特殊使用

    今天要讲的就是怎样使用<script>去请求一个servlet,加载一些js资源以及额外的逻辑处理: 目录: JS的引入的几种方式 在script的标签中引入Servlet 动态引入JS的 ...