DotNetNuke自定义窗体模块的数据结构(三)

动态SQL与存储过程
本文探讨了在DotNetNuke中使用动态SQL而非存储过程的方法,介绍了如何在运行时生成SQL语句以处理不确定数量的字段,同时保持代码灵活性。
    在接触国外的CMS等Open Source产品之前,老实说,我写过的存储过程,包括SQL Server的、Oracle的,加起来绝对不会超过5个,而且还基本上都是从网上抄袭的,主要是觉得太麻烦:嗯,是的,如果数据库设计的不够好,经常需 要改动,比如加一个字段,修改一下字段类型的话,需要从数据表、存储过程、调用等一路改上来,确实是挺麻烦的。不过习惯了之后,发现用存储过程确实有它的 好处,也被迫养成了对数据库设计要每个字段都斟酌半天的习惯,所以,我们看到DotNetNuke有近乎上千个存储过程(安装了所有的附加模块之后)。

    我现在非常喜欢使用存储过程的方式来操作数据库——不过,诚如我们在《 DotNetNuke自定义窗体模块的数据结构(二)》中所说的那样,由于我们修改了数据结构,所以,存储过程在这里使用是不太适合的。唉,好吧,我声明:我所说的并不代表我的意思,我对我说的话不承担任何责任 :(

    我们在(二)中重新把UDT的UserDefinedRows这张表(在我们的模块中已经改名了)做了修改,如果是希望在列表上显示的,或者是参与查询 的,我们都作为基本字段放在列表中;而其他的字段则作为扩展字段放在扩展表中,在用户进行定义的时候,可以选择是使用基本字段,还是扩展字段。当然,在这 种情况之下,基本字段就不可能被“用完”,在某一个Form之中,我们可能只需要基本字段中的几个而已,其他剩余的我们都不需要用到,简而言之,也就是我 们需要更新的字段是运行时决定的,而不是设计时决定的。而这个时候,如果我们在进行INSERT或者UPDATE操作的时候,是对所有的字段都操作一遍的 话,不但是有点怪,而且也容易造成错误,比如,日期型、整数型等的字段,本来明明是没有内容的,但是我们非要INSERT入内容,会出现错误,或者是不正 确的初始数据,我们希望,没有使用到的字段,就保留其为NULL就好了,不需要对该字段进行操作(大家可以插入空值或者是String.Empty试试, 会觉得很头疼)。

    所以,我们需要在运行时生成SQL语句,我们把这个函数放在下面,供大家参考。
 1           Public   Overrides   Function  AddHashRow( ByVal  field  As  Hashtable)  As   Integer
 2               Dim  sqlComm  As  SqlCommand  =   New  SqlCommand()
 3 
 4               Dim  strSql  As   String   =   " INSERT INTO RedstartFormRow ( "
 5 
 6               Dim  strField  As   String   =   ""
 7               Dim  strParm  As   String   =   ""
 8 
 9               For   Each  dic  As  DictionaryEntry  In  field
10                   If  strField  <>   ""   Then
11                      strField  =  strField  &   " "
12                   End   If
13                  strField  =  strField  &  dic.Key.ToString()
14 
15                   If  strParm  <>   ""   Then
16                      strParm  =  strParm  &   " "
17                   End   If
18                  strParm  =  strParm  &   " @ "   &  dic.Key.ToString()
19 
20                  sqlComm.Parameters.Add( New  SqlParameter( " @ "   &  dic.Key.ToString(), GetNull(dic.Value.ToString())))
21               Next
22              strSql  =  strSql  &  strField  &   " ) VALUES ( "   &  strParm  &   " ) "
23 
24              strSql  =  strSql  &   " ; select SCOPE_IDENTITY() "
25 
26               Dim  sqlConn  As   New  SqlConnection()
27              sqlConn.ConnectionString  =  ConnectionString
28              sqlConn.Open()
29              sqlComm.Connection  =  sqlConn
30 
31              sqlComm.CommandText  =  strSql
32 
33               Return   CType (sqlComm.ExecuteScalar(),  Integer )
34           End Function

    这个函数,是放在SqlDataProvider.vb文件中的。
    而按照DotNetNuke通常的方式,是使用存储过程来和数据库打交道的,也就是如下图所示:
    在 我们的处理中,没有将数据库的操作交给存储过程来完成,而是在SqlDataProvider里面,就是用SqlCommand来执行SQL语句,执行动 态的SQL插入动作。使用存储过程当然可以获得更高的执行效率,不过,通过SqlCommand也是可以的方式。除了INSERT动作之外,我们的 Update动作也是动态的,仍然是通过动态拼凑SQL语句的方式,对数据表进行更新。而在这个函数中,我们仍然调用select SCOPE_IDENTITY(),以便可以马上返回我们的值,以方便我们在程序中可能的马上要对这一条数据进行继续处理。

    在上述的方式中,我们使用到了哈希表来存储数据,哈希表的Key对应我们的字段名称,而Value则对应用户表单中输入的内容。于是,在我们的动态窗体页面上,当页面进行保存的时候,我们需要将所有的用户控件的内容读取到哈希表中,然后再调用本函数,进行插入,或者更新。

    这只是我们的基本字段的部分,除了基本字段,我们还有扩展字段,扩展字段是对UDT的UserDefinedData表(对于我们来说,是RedstartFormRowData表)进行插入,或者更新。这个就非常简单了,我们使用存储过程来实现就可以了。

    好了,大家还记得我们曾经在《 基于DotNetNuke的动态窗体支持(二)》这篇文章中定义了一个EditControls的集合吗?这个集合中包含了我们所有的用户自定义控件。OK,我们在保存的时候,需要做的事情就是
    1、遍历EditControls集合,找到所有的基本字段,将之送到一个哈希表中。然后,调用我们上面的AddHashRow的函数去保存基本字段;
    2、再遍历一遍EditControls集合,基本字段置之不理,找到扩展字段,然后逐个的调用我们保存扩展字段的存储过程,将之保存到扩展表中;

    以上就是我们对自定义窗体结构的保存过程,在这里,我没有为我们的数据结构定义对应的对象,因为我觉得,对于这样的结构,定义对象并不太好,当然,这就导致了IDataReader的大量使用,也出现了一些问题,到时候我们再来讲。

转载于:https://www.cnblogs.com/dnnworkflow/archive/2008/11/01/1324058.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值