.net中实现C#源码和数据库脚本语言的解藕

39 篇文章 1 订阅

       在开发过程中,如果开发语言能和页面脚本语言javascript、数据库脚本语言sql(以下简称SQL)等进行解藕的话,我想这是一个很不错的习惯。

       在这里以C#开发语言为准,讲述C#和SQL如何进行解藕。当然,在.net体系中提供了linq开发功能,把数据库脚本语言当成开发语言的一部分,不过linq毕竟只支持sql server数据库。

       C#开发语言和SQL进行解藕的思路很简单,先把SQL配置到XML配置文件中,再把SQL从配置文件中读取出来,最后进行解析,最终的解析结果是数据库可认的,也就是可以正确运行的。这种思路和mybatis是很相似的,说实话也是参照了mybatis后,自己才动手重写了一个,不过功能没有mybatis那么强大,不过基本满足项目日常开发。

        那为什么要重新造一个轮子?我看了mybatis后,对于mybatis我也没有深入的了解,实话实说只是很表层的接触。主要是看了一些demo范例,觉得这不是我所想要的框架,虽然它很优秀,应用广泛。为什么不是我所想要的,mybatis虽然提供了对原生态的SQL很完美的支持(这一点和Hibernate(NHibernate也是)相比灵活了很多),但它毕竟是个ORM框架,同时提供了对原生态的SQL很完美的支持。我本人对于ORM框架有抵触情绪,一直觉得ORM框架不太灵活,远没有原生态SQL灵活,在应用程序和数据库之间再建立一些模型有些多余。另外是学习成本高,特别是Hibernate家族的ORM框架,想精通不是那么容易的事情。

        先把SQL配置到XML配置文件中,再把SQL从XML配置文件中读取出来,最后进行解析。这是我的整个思路,接下来将逐一讲解。

一、 准备工作

环境:windowsXP+.net4.0+VS2010+Oracle 11g。

我们在Oracle数据库下新建一个机构表格,用于查询测试所用。表结构如下:

create table COM_SYS_DEP
(
  depid_n       NUMBER(15) not null,
  depcode_v     VARCHAR2(20),
  depname_v     VARCHAR2(50),
  parentid_n    NUMBER(15),
  iseffect_n    NUMBER(2),
  creuserid_n   NUMBER(15),
  credatetime_d DATE,
  ediuserid_n   NUMBER(15),
  edidatetime_d DATE
)

表格各字段定义如下:


测试数据如下:

insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (2, '0001', '系统机构', null, 1, null, null, 2, to_date('30-03-2012 14:10:51', 'dd-mm-yyyy hh24:mi:ss'));
insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (25, '111111', 'ddddddd', null, 2, 2, to_date('02-03-2012 09:56:22', 'dd-mm-yyyy hh24:mi:ss'), 2, to_date('20-03-2012 16:26:29', 'dd-mm-yyyy hh24:mi:ss'));
insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (22, '11', '11', 2, 1, 2, to_date('29-02-2012 17:56:46', 'dd-mm-yyyy hh24:mi:ss'), null, null);
insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (23, '22', '22', 2, 1, 2, to_date('29-02-2012 17:57:31', 'dd-mm-yyyy hh24:mi:ss'), null, null);
insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (24, '33', '33', 2, 1, 2, to_date('29-02-2012 17:58:24', 'dd-mm-yyyy hh24:mi:ss'), null, null);
insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (42, 'dd', 'dd', 2, 1, 2, to_date('20-03-2012 16:28:48', 'dd-mm-yyyy hh24:mi:ss'), null, null);
insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (43, 'cccccc', 'cccccc', null, 1, 2, to_date('20-03-2012 16:37:15', 'dd-mm-yyyy hh24:mi:ss'), 2, to_date('20-03-2012 16:42:18', 'dd-mm-yyyy hh24:mi:ss'));
insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (44, '111', '111', 43, 1, 2, to_date('20-03-2012 16:42:52', 'dd-mm-yyyy hh24:mi:ss'), null, null);
insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (45, '222', '222', 43, 1, 2, to_date('20-03-2012 16:45:28', 'dd-mm-yyyy hh24:mi:ss'), null, null);
insert into COM_SYS_DEP (depid_n, depcode_v, depname_v, parentid_n, iseffect_n, creuserid_n, credatetime_d, ediuserid_n, edidatetime_d)
values (46, '333', '333', 43, 2, 2, to_date('20-03-2012 16:45:33', 'dd-mm-yyyy hh24:mi:ss'), null, null);

下面是一个SQL配置到XML中的范例。

二、SQL配置到XML配置文件中

<?xml version="1.0" encoding="utf-8" ?>
<h namespace="com_sys_dep">
  <select id="getDep">
    SELECT T1.DEPID_N,T1.DEPNAME_V
    FROM COM_SYS_DEP T1
    WHERE T1.ISEFFECT_N=1 AND T1.DEPTYPE_N=1
    ORDER BY T1.DEPCODE_V
  </select>  
</h>
在开发中,如果按照传统方式,就是把SQL语句直接写到代码,我们可以发现,从前台或窗口会传输很多变量,再根据变量是否为空拼装成完整SQL语句,再执行。如下面代码:这个最简单的配置,没有涉及任何变量。其中,<hnamespace="com_sys_dep">是个命名空间,在这里命名空间是没有任何意义,只是增加的可读性,一般来说,命名空间的名称就是XML文件的名称。<select id="getDep">节点的属性是select,属性id是getDep。在这里节点属性一般有select、insert、update、delete分别对应查询、添加、修改、删除。节点属性id在一个配置文件中是必须是唯一的。

<%
    var sql = "SELECT T1.DEPID_N,T1.DEPNAME_V FROM COM_SYS_DEP T1 WHERE 1=1";
    if(Request["ISEFFECT_N"]!=null)
    {
        sql += " AND T1.ISEFFECT_N="+int.Parse(Request["ISEFFECT_N"].ToString());
    }
    if (Request["DEPNAME_V "] != null)
    {
        sql += " AND T1. DEPNAME_V =’"+ Request["DEPNAME_V "].ToString()+"’";
    }
    if (Request["PARENTID_N"] != null)
    {
        sql += " AND T1. PARENTID_N IN (‘’"+ Request["PARENTID_N "].ToString()+"’)";
    }
    sql += " ORDER BY T1.DEPCODE_V";
%>

如果要把上述的代码在XML实现的话,那思路是什么?利用XML的特性,在XML中类似开发语言一样,设置判断分支,对XML进行解析的时候进行判断,如果对应的变量存在的话,获取分支中的SQL语句。把上述的代码在XML进行如下配置:

<select id="getDep">
    SELECT T1.DEPID_N,T1.DEPNAME_V
    FROM COM_SYS_DEP T1
    WHERE 1=1
    <if property="ISEFFECT_N" type="notSmartNull" value=""> AND T1.ISEFFECT_N = $ISEFFECT_N</if>
    <if property=" DEPNAME_V " type="notSmartNull" value=""> and T1. DEPNAME_V = #DEPNAME_V</if>
    <if property="PARENTID_N" type="notSmartNull" value=""> and T1. PARENTID_N IN @PARENTID_N</if>
    ORDER BY T1.DEPCODE_V
</select>

也许大家已经注意到,$ISEFFECT_N、#DEPNAME_V和@PARENTID_N两个字符串,这三个字符串分别表示三个变量,如果对ibatis了解的话,很容易理解。在开发中,我们面对很多种数据类型的变量,如:字符串、整数、布尔型及引用类型等等,当然,在这里是没有那么多种数据类型的变量,只有字符串和数字类型两种变量,数字类型包括整数、实数等数据类型。字符串和数字类型两种变量类型分别以#和$表示,前面提到的$ISEFFECT_N和#DEPNAME_V两个变量,就都表示数据类型和字符串类型。除了#和$分别表示两种数据类型外,还有@这种类型,它对应sql中的in关键字。这样是很容易理解,假设从前台传输一个value=100的参数,$value会解析成100,#value会解析成‘100’,@value,会解析成(‘100’)

三、把SQL从XML配置文件中读取出来

我们定义TranSql和XmlReader两个类用于读取XML配置中的SQL,除外,还需要两个辅助类,分别是ComInput和Consts,现在分别介绍这四个类。

Ø  Consts

常量类,专门用于存储相关常量。

Ø  ComInput

这个类是比较重要的一个类,用于存放XML SQL中的变量值,继承于Dictionary<string,object>泛型类。

Ø  XmlReader

该类是核心类,用于读取配置在XML中的SQL,不过还需要进一步的解析,解析是TranSql类的工作。

Ø  TranSql

该类也是核心类,用于解析XmlReader类读取的最原始SQL,最终的解析结果可以在数据库运行。

对于这四个类,在这里我没有粘帖代码,大家有兴趣可下载代码研究。

源码下载地址:http://download.csdn.net/download/ddxkjddx/4201614

四、Demo

<%
   var comInput = new ComInput();
   comInput.SetPm("ISEFFECT_N", "1");
   comInput.SetPm("DEPNAME_V", "组织机构");
   var sql = TranSql.GetSqlFormXml("xml.com_sys_dep.getDep", comInput);
   Response.Write(sql);
%>
输出结果:

SELECT T1.DEPID_N,T1.DEPNAME_V FROM COM_SYS_DEP T1 WHERE 1=1 AND T1.ISEFFECT_N = 1 and T1. DEPNAME_V = '组织机构' ORDER BY T1.DEPCODE_V




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值