写在前面


在上一小节中,我们学习、实践和总结记录了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. 第08组 Alpha冲刺(2/4)

    队名 八组评分了吗 组长博客 小李的博客 作业博客 作业链接 组员1李昕晖(组长) 过去两天完成了哪些任务 文字/口头描述 11月17日了解各个小组的进度与难以攻破的地方,与隔壁第七组组长讨论进度发展 ...

  2. 【深入学习linux】在linux系统下怎么编写c语言程序并运行

    1. 首先安装下 gcc : centos yum -y gcc 2. 编写c程序保存hello.c: #include <stdio.h> #include <stdlib.h&g ...

  3. DB2数据库基础

    一.DB2数据库安装教程 DB2安装教程:https://jingyan.baidu.com/article/e75057f2f59ef9ebc91a8905.html 二.DB2常用命令 1. 打开 ...

  4. [转]详解vue父组件传递props异步数据到子组件的问题

    原文地址:https://www.cnblogs.com/goloving/p/9114389.html 案例一 父组件parent.vue // asyncData为异步获取的数据,想传递给子组件使 ...

  5. weui.js汉字乱码

    2019-6-25 11:04:13 星期二 min.js 源文件中会自带乱码: 鍙栨秷:  取消; 纭畾:   确定; 方案: 把weui.js用notepad++打开, 搜索乱码字符, 替换掉, ...

  6. Django ORM 以连接池方式连接底层连接数据库方法

    django原生支持是不支持 以连接池方式连接数据库的 概述 在使用 Django 进行 Web 开发时, 我们避免不了与数据库打交道. 当并发量低的时候, 不会有任何问题. 但一旦并发量达到一定数量 ...

  7. 对step文件进行信息抽取算法

    任务描述:给定一个step文件,对该文件的字符串进行信息抽取,结构化的组织文件描述模型的数据.形成抽象化数据结构,存入计算机数据库.并能按照有条理结构把这些数据展示出来. 信息抽取的结果描述: 1 数 ...

  8. (十)redis源码解读

    一.redis工作机制 redis是 单线程,所有命令(set,get等)都会加入到队列中,然后一个个执行. 二.为什么redis速度快? 1.基于内存 2.redis协议resp 简单.可读.效率高 ...

  9. JAVA SpringBoot2 整合 ueditor 的 并实现前后端分离

    1,下载 jsp 版本的 百度编辑器,点击此处下载 2,解压文件,解压后目录如下 3,我们将 jsp 目录暂时移动到别的地方,剩下的文件作为一个 H5 前端项目使用,笔者这边导入到 idea 进行开发 ...

  10. linux 安装 btrace

    1.下载btrace https://github.com/btraceio/btrace/releases/download/v1.3.8.3-1/btrace-bin-1.3.8.3.tgz2.上 ...