轻量级ORM框架——第二篇:Dapper中的一些复杂操作和inner join应该注意的坑
上一篇博文中我们快速的介绍了dapper的一些基本CURD操作,也是我们manipulate db不可或缺的最小单元,这一篇我们介绍下相对复杂
一点的操作,源码分析暂时就不在这里介绍了。
一:table sql
为了方便,这里我们生成两个表,一个Users,一个Product,sql如下:
<1> Users table
CREATE TABLE [dbo].[Users](
[UserID] [int] IDENTITY(1,1) NOT NULL,
[UserName] [varchar](50) NULL,
[Email] [varchar](100) NULL,
[Address] [varchar](100) NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[UserID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
<2> Product table
CREATE TABLE [dbo].[Product](
[ProductID] [int] IDENTITY(1,1) NOT NULL,
[ProductName] [varchar](220) NULL,
[ProductDesc] [varchar](220) NULL,
[UserID] [int] NULL,
[CreateTime] [datetime] NULL,
CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED
(
[ProductID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
二:in操作
很多时候我们在manipulate table的时候,或多或少的都会用到 ”in关键字”,比如:我要找到User表中Email in ('5qq.com','8qq.com')的
Users record。。。
static void Main(string[] args)
{
var connection = new SqlConnection("Data Source=.;Initial Catalog=Datamip;Integrated Security=True;MultipleActiveResultSets=True"); var sql = "select * from Users where Email in @emails"; var info = connection.Query<Users>(sql, new { emails = new string[] { "5qq.com", "7qq.com" } });
}

看了上面的操作,是不是很简单,只要我们的参数类型是Array的时候,dappper会自动将其转化。。。
三:多条sql一起执行
有时候我们会想在一条sql中灌入很多的snippet sql,然后让其一起执行,此时让我想起了一个操作,我会在db中load data的时候会写到
select ... from marketing where id in (....); select .... from eventmarketing where in (...)类似这样的语句,然后进行结果合并,这篇
为了方便演示,在User上做一个*操作,在Product上做一个* 操作,比如下面这样:
static void Main(string[] args)
{
var connection = new SqlConnection("Data Source=.;Initial Catalog=Datamip;Integrated Security=True;MultipleActiveResultSets=True"); var sql = "select * from Product; select * from Users"; var multiReader = connection.QueryMultiple(sql); var productList = multiReader.Read<Product>(); var userList = multiReader.Read<Users>(); multiReader.Dispose();
}

四:多表join操作
不管sql写的多么好或者多么烂,接触一个月还是接触到十年,都必然跑不了多表查询,那么在多表查询上dapper该如何使用呢???比如
说我要找到2015-12-12之后的商品信息和个人信息,很显然这是一个多表查询,可以先来看一下users和product的关系。

可以发现其实他们有一个外键关系,然后我们在Product Entity上做一下小修改,将Users作为Product的一个entity property。。。
public class Product
{
public int ProductID { get; set; } public string ProductName { get; set; } public string ProductDesc { get; set; } public Users UserOwner { get; set; } public string CreateTime { get; set; }
}
有了这些储备,我们大概就可以写出如下的sql。
static void Main(string[] args)
{ var connection = new SqlConnection("Data Source=.;Initial Catalog=Datamip;Integrated Security=True;MultipleActiveResultSets=True"); var sql = @"select p.ProductName,p.CreateTime,u.UserName
from Product as p
join Users as u
on p.UserID = u.UserID
where p.CreateTime > '2015-12-12'; "; var result = connection.Query<Product, Users, Product>(sql,
(product, users) =>
{
product.UserOwner = users; return product;
}); }
结果就是”操!!!!“。。。。。。。。。。。。

从错误信息中可以看到:当你使用multi-mapping的时候要确保设置了splitOn参数,除了Id。。。从这句话中好像也看不出什么名堂,也就是说
除了Id,你都需要设置SplitOn参数,好吧,这是逼着哥哥看源代码。。。。看看SplitOn到底是个什么样的鸟玩法。。。然后我从Call Stack往上
面找,发现了非常”至关重要“的一段话。

然来splitOn就是Dapper对DataReader进行”从右到左“的扫描,这样就可以从sequent中获取到一个subsequent,然后遇到设置的splitOn
就停止。。。然来是这样,哈哈。。。这回我就知道了,将splitOn设置为”userName“就好了。。。比如下面这样。。。
static void Main(string[] args)
{ var connection = new SqlConnection("Data Source=.;Initial Catalog=Datamip;Integrated Security=True;MultipleActiveResultSets=True"); var sql = @"select p.ProductName,p.CreateTime,u.UserName
from Product as p
join Users as u
on p.UserID = u.UserID
where p.CreateTime > '2015-12-12'; "; var result = connection.Query<Product, Users, Product>(sql,
(product, users) =>
{
product.UserOwner = users; return product;
},splitOn: "UserName"); }

当然如果你觉得我上面说的太啰嗦了,注意事项还tmd的多,又是泛型,又是Lambda的。。。你也可以不指定这些具体Type,而默认使用
dynamic也是可以的,比如下面这样:

五:支持存储过程
对于存储过程,也是一个不得不说的话题,我们的dapper同样也是可以执行的,只需要在Query中的CommandType中标记一下当前就是一个
StoredProcedure就八九不离十了,比如现在在Users表上创建一个简单的StoredProcedure。
USE [Datamip]
GO
/****** Object: StoredProcedure [dbo].[sp_GetUsers] Script Date: 09/02/2016 09:14:04 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create proc [dbo].[sp_GetUsers]
@id int
as
begin
select * from Users where UserID = @id ;
end
在这里,我们需要向存储过程塞入一个@id参数,返回具体的Users EntityList,好了,下面再看一下Query如何构造。
static void Main(string[] args)
{
var connection = new SqlConnection("Data Source=.;Initial Catalog=Datamip;Integrated Security=True;MultipleActiveResultSets=True"); var info = connection.Query<Users>("sp_GetUsers", new { id = },
commandType: CommandType.StoredProcedure);
}

搞定,感觉用Dapper是不是就这么简单,先就说到这里,希望对大家有帮助。
轻量级ORM框架——第二篇:Dapper中的一些复杂操作和inner join应该注意的坑的更多相关文章
- 轻量级ORM框架:Dapper中的一些复杂操作和inner join应该注意的坑
上一篇博文中我们快速的介绍了dapper的一些基本CURD操作,也是我们manipulate db不可或缺的最小单元,这一篇我们介绍下相对复杂 一点的操作,源码分析暂时就不在这里介绍了. 一:tabl ...
- 轻量级ORM框架——第一篇:Dapper快速学习
我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db,而且市面上的orm框架有很多,其中有一个框架 叫做dapper,而且被称为th ...
- 分享自己写的基于Dapper的轻量级ORM框架~
1.说明 本项目是一个使用.NET Standard 2.0开发的,基于 Dapper 的轻量级 ORM 框架,包含基本的CRUD以及根据表达式进行一些操作的方法,目前只针对单表,不包含多表连接操作. ...
- C# 性能优化 之 秒表 Stopwatch。 Dapper一个和petapoco差不多的轻量级ORM框架
Sweet小马 小马同学的编程日记. C# 性能优化 之 秒表 Stopwatch. 生词解释:Diagnostics[,daɪəg'nɑstɪks] n.诊断学 using System.Diagn ...
- .NET轻量级ORM框架Dapper入门精通
一.课程介绍 本次分享课程包含两个部分<.NET轻量级ORM框架Dapper修炼手册>和<.NET轻量级ORM框架Dapper葵花宝典>,阿笨将带领大家一起领略轻量级ORM框架 ...
- 轻量级ORM框架Dapper应用一:Dapper安装
一.Dapper简介 Dapper是一款轻量级ORM框架,为解决网站访问流量极高而产生的性能问题而构造,主要通过执行TSQL表达式而实现数据库的CQRS. 如果你在项目中遇到性能访问问题,选择Dapp ...
- Farseer.net轻量级开源框架 中级篇:探究ORM(Mapping)
导航 目 录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 中级篇: SQL执行报告 下一篇:Farseer.net轻量级开源框架 中级篇: Cooki ...
- 轻量级ORM框架初探-Dapper与PetaPoco的基本使用
一.EntityFramework EF是传统的ORM框架,也是一个比较重量级的ORM框架.这里仍然使用EF的原因在于为了突出轻量级ORM框架的性能,所谓有对比才有更优的选择. 1.1 准备一张数据库 ...
- Farseer.net轻量级开源框架 中级篇:UrlRewriter 地址重写
导航 目 录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 中级篇: Cookies.Session.Request 下一篇:Farseer.net轻量 ...
随机推荐
- is和as
一.明确两个基本概念 隐式转换: a.对于值类型,低精度=>高精度.eg:int=>long b.对于引用类型,子类向祖宗类转换过程.eg:对象=>Object 显式转换:显示转换是 ...
- ios 常见问题解决
一,libxml/HTMLparser.h file not find 第一种方法: 点击左边项目的根目录,再点击右边的Build Settings,手工输入文字:“Header search pat ...
- Spark join 源码跟读记录
PairRDDFunctions类提供了以下两个join接口,只提供一个参数,不指定分区函数时默认使用HashPartitioner;提供numPartitions参数时,其内部的分区函数是HashP ...
- jQuery? 回归JavaScript原生API
如今技术日新月异,各类框架库也是层次不穷.即便当年漫山红遍的JQuery(让开发者write less, do more,So Perfect!!)如今也有被替代的大势.但JS原生API写法依旧:并且 ...
- angular2
1 class两种写法 (1).直接写 class="{{}}"; (2).数组 arr[a,b,c] ng-class = "arr" 2.class和sty ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(28)-系统小结
系列目录 我们从第一节搭建框架开始直到二十七节,权限管理已经告一段落,相信很多有跟上来的园友,已经搭配完成了,并能从模块创建授权分配和开发功能了 我没有发布所有源代码,但在14节发布了最后的一次源代码 ...
- Linux 14.04lts 环境下搭建交叉编译环境arm-linux-gcc-4.5.1
交叉编译工具链是为了编译.链接.处理和调试跨平台体系结构的程序代码,在该环境下编译出嵌入式Linux系统所需要的操作系统.应用程序等,然后再上传到目标板上. 首 先要明确gcc 和arm-linux- ...
- node实现watcher的困境
@(node,watcher) watcher,在如今的前端领域已经数见不鲜了.目前流行的gulp流程工具提供了watcher的选项,是我们在开发过程中不需要手动进行触发构建流程,转而根据文件(目录) ...
- (福利)分享一个用android编写的简单的APP——爱吖天气
这是本人随便编写的一个天气的APP,超级简单. 项目已同步至:https://github.com/nanchen2251/AiYaWeatherDemo 基本实现了天气查看,闪屏引导,天气基本信息, ...
- 剖析并利用Visual Studio Code在Mac上编译、调试c#程序
0x00 前言 一周多以前的微软的Build大会上,微软发布了一个让很多人眼前一亮的工具,也是本文的主角——Visual Studio Code.很多使用Windows的朋友都很高兴,认为又多了一个很 ...