.NET Framework 2.0 中,Microsoft 在 System.Data.Common 名称空间下定义了一组类用来让程序员编写适用于不同数据库的数据访问代码,而且还在 Enterprise Library 中提供了一个标准的示范。但是这里面有很大的一个问题就是当程序员使用带参sql的方式来访问数据库时,一切都变得毫无意义了。因为 SQL Server 支持以 @ 为前缀的名称参数、Oracle 则支持以 : 为前缀的名称参数,而当使用 OleDb 访问 Access 时就变成了使用 ? 作为占位符的位置参数语法。在编写程序时,必须针对不同的 ADO.NET Provider 编写 sql 语句。

本文将介绍一种方法,可以使得 SQL Server、Oracle 也支持以 ? 为占位符的位置参数语法。要想实现这个效果,就需要将 sql 语句中的 ? 占位符替换成相应的名称参数。下面以 SQL Server 数据库为例,假如有一条 sql 语句:

select count(0) from sys_user where user_code=? and password=?

如果能够将其转变为:

select count(0) from sys_user where user_code=@p1 and password=@p2

就可以使 SQL Server 也支持以 ? 为占位符的位置参数了。

在做这个变换时,我使用了一个正则表达式。通过这个正则表达式,可以将 sql 语句中的所有 ? 占位符找到,并将其替换为以 @ 为前缀的位置参数,代码如下:

private string PreparePlaceHolder(string srcSql)
{
string _sqlTokenPattern = "[\\s]+|(?<string>'([^']|'')*')|(?<comment>(/\\*([^\\*]|\\*[^/])*\\*/)|(--.*))|(?<parametermarker>\\?)|(?<query>select)|(?<identifier>([\\p{Lo}\\p{Lu}\\p{Ll}\\p{Lm}\\p{Nd}\\uff3f_#$]+)|(\"([^\"]|\"\")*\"))|(?<other>.)";
Regex sqlTokenParser = new Regex(_sqlTokenPattern, RegexOptions.ExplicitCapture); List<Group> groups = new List<Group>();
bool flag = false; for (Match match = sqlTokenParser.Match(srcSql); Match.Empty != match; match = match.NextMatch())
{
if (!match.Groups["comment"].Success)
{
if ((match.Groups["comment"].Success || match.Groups["string"].Success) || match.Groups["other"].Success)
{
flag = true;
}
else if (match.Groups["query"].Success)
{
if (!flag)
{
// 走到这里,表示这是一条 select 语句。
}
}
else if (match.Groups["parametermarker"].Success)
{
// 走到这里,表示发现了一个 ? 占位符。
groups.Add(match.Groups["parametermarker"]);
}
}
} StringBuilder desSql = new StringBuilder(srcSql); for (int i = groups.Count - ; i >= ; i--)
{
Group group = groups[i]; desSql.Remove(group.Index, group.Length);
desSql.Insert(group.Index, ParameterToken + "p" + (i + ));
}
return desSql.ToString();
}

利用上述方法,可以编写出更加通用的 SQLHelper 类。程序员可以在任何时候使用位置参数语法来执行 sql 语句,而不必考虑对应的 ADO.NET Provider 是否支持位置参数。

最新文章

  1. JavaScript中style, currentStyle和 getComputedStyle的异同
  2. 使用Microsoft Fakes进行单元测试(1)
  3. jsp页面间传递参数 中文乱码问题(zz)
  4. web.xml文件的作用
  5. 可扩展的listview--Expandablelistview
  6. JBoss AS 7性能调优(三)
  7. ubuntu 安装maven提示出错 The program &amp;#39;mvn&amp;#39; can be found in the following packages
  8. window.onload多个共存 - 借鉴jQuery.noConflict的思路
  9. SQL总结手册
  10. RFID和QRCODE对比
  11. 在java中如何处理日期格式问题
  12. BFS总结
  13. codeforces 494a//Treasure// Codeforces Round #282(Div. 1)
  14. robot framework学习笔记之七—连接mysql数据库
  15. Android环境搭建及Ionic打包(win7)
  16. VMware虚拟机创建安装之后不出现VMnet1和VMnet8虚拟网卡
  17. HTML inline 与block元素
  18. gitlab改root密码
  19. 1.nginx安装和配置
  20. 阿里云 linux 找回mysql root密码

热门文章

  1. iOS10隐私设置及相应问题
  2. ExecuteReader(),ExecuteNonQuery(),ExecuteScalar(),ExecuteXmlReader()之间的区别
  3. grep 和 sed:linux经常使用工具 &amp;amp; 基本正則表達式
  4. Endian.BIG_ENDIAN和Endian.LITTLE_ENDIAN(http://smartblack.iteye.com/blog/1129097)
  5. C# 获取网站的 IIS 站点名称 ,获取站点当前连接数
  6. UVA 10603 Fill
  7. global变量
  8. Prim算法(普里姆算法)
  9. BZOJ 3648: 寝室管理( 点分治 + 树状数组 )
  10. WARNING [Project: :app] To shrink resources you must also enable ProGuard