我手头有个古老的项目,持久层用的是古老的ADO.net。前两天去昆明旅游,其中的一个景点是云南民族村,通过导游介绍知道了一个古老的民族——基诺族,“基”在这个族内代表舅舅,“基诺”意为“跟在舅舅后边”,加以引申即为“尊崇舅舅的民族”,很有意思吧,这是我国最后一个被发现并确认下来的少数民族,即第56个民族。  项目里的ado.net和基诺族一样古老。

话说,项目里数据访问层,好多都是拼的sql,这给sql注入提供了可乘之机,为了系统安全,决定在有限的时间内,将它改成参数化。

其中,有个根据多个订单号查询支付单的方法,签名如下:

public DataTable GetAlipayNotifyRecords(AlipayPaymentStatus status, params string[] trade_no)

那么,问题来了,因为sql里有in, 而 in(@no)的方式是行不通的。

怎么办呢?  首先想到的是对参数做处理:

public DataTable GetAlipayNotifyRecords(AlipayPaymentStatus status, params string[] trade_no)
{string sql = @"select * from T_AlipayNotityRecord where trade_status=@trade_status and trade_no in(@trade_no)";//string inValue = "'" + string.Join("','", trade_no) + "'";//= string.Join(",", trade_no)string inValue = "";trade_no.ToList().ForEach(no => inValue += " union all select '" + no+"'");inValue = inValue.Substring(" union all".Length);List<SqlParameter> paramList = new List<SqlParameter>(){new SqlParameter("@trade_status",status.ToString()), new SqlParameter("@trade_no",inValue),};var ds = SqlHelper.SqlDataSet(ConfigFile.PayCenterConnection, sql, CommandType.Text, paramList.ToArray());if (ds == null || ds.Tables.Count == 0)return null;return ds.Tables[0];
}

经测试,无效。经分析可知,sqlhelper会把你参数值当成字符串,不会对其做转义。所以,不管怎么对参数值处理,都还是一串字符串。

按这样的原理往下想,只能是将单号分开来传递给sql了。那么正好sql的in可以通过如下几种方式等效实现:

  • sql里有临时表,可以in一个临时表--这时,可以考虑and trade_no in(select @p1 union all select @p2 union all...)的方式
  • 把sql的in集合,转换为一个用or拼接起来的集合---即,and (trade_no=@p1 or trade_no=@p2 or trade_no=@p3 or...)

如下代码是按照后者的思路解决了这个问题:

public DataTable GetAlipayNotifyRecords(AlipayPaymentStatus status, params string[] trade_no)
{string sql = @"select * from T_AlipayNotityRecord where trade_status=@trade_status and ({0})";List<SqlParameter> paramList = new List<SqlParameter>(){new SqlParameter("@trade_status",status.ToString()), };string sql1 = "";for (int i=0;i<trade_no.Length;i++){sql1 += " or trade_no=@no" + i;paramList.Add(new SqlParameter("@no" + i, trade_no[i]));}sql = string.Format(sql, sql1.Substring(" or ".Length));var ds = SqlHelper.SqlDataSet(ConfigFile.PayCenterConnection, sql, CommandType.Text, paramList.ToArray());if (ds == null || ds.Tables.Count == 0)return null;return ds.Tables[0];
}

【结语】无意中从园子里看到一篇文章,不该活着的SqlHelper和DBHelper,很赞!

-----2016-12-13 09:39:32

【续】方法总比问题多

今天早上刷牙时,灵光一现,对于昨天的方案,不需要通过借助or或union的方式来更改sql的in了,即,可以直接生成如下的sql语句:

select * from T_AlipayNotityRecord where trade_status=@trade_status and trade_no in(@no0,@no1,...)

程序代码在上面的基础上稍做处理:

public DataTable GetAlipayNotifyRecords(AlipayPaymentStatus status, params string[] trade_no)
{string sql = @"select * from T_AlipayNotityRecord where trade_status=@trade_status and trade_no in({0})";List<SqlParameter> paramList = new List<SqlParameter>()
{new SqlParameter("@trade_status",status.ToString()),
};string sql1 = "";for (int i = 0; i < trade_no.Length; i++){sql1 += ",@no" + i;paramList.Add(new SqlParameter("@no" + i, trade_no[i]));}sql = string.Format(sql, sql1.Substring(",".Length));var ds = SqlHelper.SqlDataSet(ConfigFile.PayCenterConnection, sql, CommandType.Text, paramList.ToArray());if (ds == null || ds.Tables.Count == 0)return null;return ds.Tables[0];
}

这样子生成的sql就很直观了。比上面方案的还简短。

转载于:https://www.cnblogs.com/buguge/p/6165972.html

SqlHelper中IN集合场景下的参数处理相关推荐

  1. asp.net core中负载均衡场景下http重定向https的问题

    上周欣喜地发现,微软官方终于针对 asp.net core 在使用负载均衡的情况下从 http 强制重定向至 https 的问题提供了解决方法. app.UseForwardedHeaders(new ...

  2. 《vSphere性能设计:性能密集场景下CPU、内存、存储及网络的最佳设计实践》一1.1.1 确定参数...

    本节书摘来华章计算机<vSphere性能设计:性能密集场景下CPU.内存.存储及网络的最佳设计实践>一书中的第1章 ,第1.1节,[美] 克里斯托弗·库塞克(Christopher Kus ...

  3. Android camera (12)---camera ap在特殊的应用场景下额外使用一套独立的camera tuning参数

    camera ap在特殊的应用场景下额外使用一套独立的camera tuning参数 解决方案: 1, nvram_drv.h core\featureio\drv\inc 中添加下面的interfa ...

  4. 如何实现情感分析在舆情场景下的千人千面效果——情感分析在舆情中的研发实践(上)

    编者按 文本情感分析是对带有主观感情色彩的文本进行分析.处理.归纳和推理的过程.互联网上每时每刻都会产生大量文本,这其中也包含大量的用户直接参与的.对人.事.物的主观评价信息,比如微博.论坛.汽车.购 ...

  5. c++结构体总结(结构体定义,结构体数组,结构体指针,结构体嵌套结构体,结构体做函数参数,结构体中 const使用场景)

    看完b站黑马程序员之后的借鉴和笔记 1.什么是结构体,有什么作用? 在C/C++中,结构体是用户定义的数据类型.它可以把几种不同类型的数据项集合成结构体这样一个单一类型. 2. 结构体定义和使用 #i ...

  6. Disruptor框架中生产者、消费者的各种复杂依赖场景下的使用总结-我见过最好的Disruptor

    更多高并发知识请访问 www.itkc8.com 非常感谢 https://www.cnblogs.com/pku-liuqiang/p/8544700.html Disruptor是一个优秀的并发框 ...

  7. 【博客578】LVS NAT配合MASQUERADE实现FULLNAT的场景,及此场景下net.ipv4.vs.conntrack参数的重要作用

    LVS NAT配合MASQUERADE实现FULLNAT的场景,及此场景下net.ipv4.vs.conntrack参数的重要作用 1.LVS基本原理: 流程: 当用户向负载均衡调度器(Directo ...

  8. 简单的机器学习程序_自闭症应用场景下利用机器学习和深度学习方法进行情绪识别,并在小程序中查询识别结果...

    注:实现本文Python代码需要的包:opencv.numpy.matplotlib.sklearn.os,Python版本为Python3.7 为了使每段代码效果更直观,本文将会以类似jupyter ...

  9. 沟通技巧-《好好说话》书中的精髓:掌握沟通、说服、谈判、演讲、辩论的五维话术,让你在任何场景下,都能做到处变不惊,学会说话这个技术活。

    <好好说话>书中的精髓:掌握沟通.说服.谈判.演讲.辩论的五维话术,让你在任何场景下,都能做到处变不惊,学会说话这个技术活. 相信在生活中,每个人都可能因为不会说话遇到一些困难: 工作辛苦 ...

最新文章

  1. 过滤流的主要特点是什么_高效过滤器工艺流程是什么 高效过滤器特点介绍【详解】...
  2. Java mybatis实现mysql批量插入
  3. python打印自动换行如何解决_解决python DataFrame 打印结果不换行问题
  4. linux sort 命令详解(转 )
  5. 《Python编程从入门到实践》学习笔记6:字典
  6. 「JavaScript面向对象编程指南」原型
  7. 豆瓣9.8分,周志明的《凤凰架构》,高屋建瓴,推荐(送书)
  8. [收藏]网络营销十道羊皮卷
  9. issues:close 云端 STS 启动报找不到 jdk
  10. 74ls90设计十进制计数器电路图_利用555与74ls90制作电子秒表
  11. sql server 跟踪_SQL Server作业性能–跟踪
  12. PostgreSQL的checkpoint能否并行
  13. 低解密指数攻击_CTF中RSA的一些攻击思路
  14. (解决办法)Windows Server 2003安装sp1时说产品密钥无效
  15. Windows server 2012 系统安装 密钥
  16. python属于汇编语言还是高级语言_python语言属于汇编语言吗?_后端开发
  17. 25.HTTP协议和WEB服务器APACHE
  18. 推荐的五款市面上常用的免费CMS建站系统
  19. 测试岗面试,一份好的简历总可以让人眼前一亮
  20. CM安装成功,CM的web界面登录不上解决方案

热门文章

  1. html form表单提交数据并后台获取
  2. 二进制 java Class文件解析实例
  3. 软件架构设计之常用架构模式
  4. go防止多次递交表单
  5. 前端一HTML:十七:背景
  6. html5中的dom中的各种节点的层次关系是怎样的
  7. 【Visual Studio】如何在VS 2012中打印变量值到输出窗口
  8. 一起从头学习Flex
  9. Tomcat 配置WEB虚拟映射 及 配置虚拟主机
  10. Shiro 那点事儿