[ASP数据库封装驱动。 Drunk Dream-

来源:百度文库 编辑:神马文学网 时间:2024/04/20 06:12:26
ASP数据库封装驱动。
错误多多,还请各位大虾多多指教。
思路:
原来的方案:
我们是首先根据数据库的字段和实际需求设计Web表单,然后从Web表单获取提交的数据集,然后在服务段将提交的数据集和数据库的字段一一对应,然后再一一作过滤和处理……
现在的方案:
直接从数据库生成框架缓存,将每一个表的字段及其相关属性(类型要求、必填、长度、默认值……)储存在全局数组中。当外部提交某张表单时,从对应的全局数组中生成相应的Dictionary对象,然后依据这个和数据表完全映射的Dictionary遍历获取对应的提交值,由此替代了一一对应和读取的繁琐过程。
实现部分被简化为:
for i=0 to Ubound(KeysArray)-1
Key=KeysArray(i,0)
Item=Request(md5(Key))
objDict.Add Key,Item
next
也就是说,这是和传统方案完全相反的思路,这个思路保证了所获取的数据一定是数据库所需要的数据,数据库要求的数据类型或者必须为空的数据如果出现异常则必然会出错,等等。
最后在实现表单处理的语句简化为,其他的一切操作都被封装在类中:
Call System_Initialize()
Dim objUser ‘新建对象
Set objUser = new TUser
objUser.Table="Comm_User" ‘指定数据表
If objUser.Creat Then ‘建立表的Dictionary对象
objUser.ValidAndTransfer() ‘获取数据、验证并转入最终的数据驱动层
objUser.Update() ‘更新该表数据
End IF
Set objUser = nothing
Call System_Terminate()
与之配套的另外一个方面是从缓存的数据表框架中按照实际表单的需要自动生成Web表单,显示在客户端。
在SQL Server中遍历当前数据库的所有用户表
SELECT Table_name
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_TYPE <> ‘VIEW‘)
Table_name:表名;
TABLE_TYPE:表的类型;
参见:SQL Server联机手册,T-SQL参考,信息架构视图。
又及:ACCESS下也可实现相关的功能[1]
在SQL Server中遍历指定表的字段及属性
SELECT Column_name,IS_NULLABLE,DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (TABLE_NAME = ‘myTableName‘)
TABLE_NAME:表名;
Column_name:列名;
IS_NULLABLE:是否允许为空;
DataType:系统数据类型;
ORDINAL_POSITION:列标识号;
COLUMN_DEFAULT:列的默认值;
CHARACTER_OCTET_LENGTH:以字节为单位的最大长度,适于二进制数据、字符数据,或者文本和图像数据。否则,返回 NULL。
从数据库生成当前库所有表全局Array缓存
strSQL="SELECT Table_name FROM INFORMATION_SCHEMA.TABLES WHERE (TABLE_TYPE<>‘VIEW‘)"
Set objRS_table= objConn.Execute(strSQL)
do while not objRS_table.EOF
strSQL="SELECT Column_name,DATA_TYPE,IS_NULLABLE,COLUMN_DEFAULT,CHARACTER_OCTET_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE (TABLE_NAME = ‘"& objRS_table("Table_name") &"‘)"
set objRS_column=server.createobject("adodb.recordset")
objRS_column.open strSQL,objConn,1,1
Dim i,TableTemp
i=0
ReDim TableTemp(objRS_column.RecordCount,4)
do while not objRS_column.EOF
TableTemp(i,0)=objRS_column(0)
TableTemp(i,1)=objRS_column(1)
TableTemp(i,2)=objRS_column(2)
TableTemp(i,3)=objRS_column(3)
TableTemp(i,4)=objRS_column(4)
i=i+1
objRS_column.movenext
loop
Set objRS_column= nothing
application(objRS_table(0))=TableTemp
objRS_table.movenext
loop
数据驱动层
<%
‘******************************************************
‘底层A:对DataBase操作的封装。
‘返回错误代码头:DB
‘******************************************************
Class TDBDriver
Public objDict
Private Table
Private KeysArray
Private ItemArray
Private objRS
Private strSQL
Private SQL_Start
Private SQL_Main
Private SQL_Join
Private SQL_Where
Private SQL_Order
Private SQL_Group
Public PageSize
Private ErrorMsg
‘插入一条数据或者更新指定的条目
Public Function Update()
If objDict.Item(KeysArray(0,0))="" Then
SQL_Start="Insert into "& Table
SQL_Main=" ("
‘从有数据的部分对应更新入数据库
For i=1 to objDict.Count-1
If Not ItemArray(i)="" Then
SQL_Main= SQL_Main & KeysArray(i,0) &","
End If
Next
‘去掉最后一个“,”
SQL_Main=Left(SQL_Main,Len(SQL_Main)-1)
SQL_Main= SQL_Main &") Values("
For i=1 to objDict.Count-1
If Not ItemArray(i)="" Then
If KeysArray(i,1)="int" Then
SQL_Main= SQL_Main & objDict.Item(KeysArray(i,0))
Else
SQL_Main= SQL_Main &"‘"& objDict.Item(KeysArray(i,0)) &"‘"
End if
SQL_Main= SQL_Main &","
End If
Next
‘去掉最后一个“,”
SQL_Main=Left(SQL_Main,Len(SQL_Main)-1)
SQL_Main= SQL_Main &")"
Else
SQL_Start="Update "& Table &" Set "
For i=1 To objDict.Count-1
If Not ItemArray(i)="" Then
SQL_Main= SQL_Main &" ("& KeysArray(i,0) &"="
If KeysArray(i,1)="int" Then
SQL_Main= SQL_Main & objDict.Item(KeysArray(i,0))
Else
SQL_Main= SQL_Main &"‘"& objDict.Item(KeysArray(i,0)) &"‘"
End if
SQL_Main= SQL_Main &"),"
End IF
Next
‘去掉最后一个“,”
SQL_Main=Left(SQL_Main,Len(SQL_Main)-1)
SQL_Where=" Where "& KeysArray(0,0) &"="& objDict.Item(KeysArray(0,0))
End if
strSQL=SQL_Start & SQL_Main & SQL_Where
‘objConn.Execute(strSQL)
Response.Write strSQL
Update=True
End Function
‘删除数据
Public Function Delete()
If objDict.Item(KeysArray(0,0))="" Then Call ShowError(ErrorMsg,01) :Exit Function
SQL_Start="Delete From "& Table
SQL_Where=" Where "& KeysArray(0,0) &"="& objDict.Item(KeysArray(0,0))
strSQL=SQL_Start & SQL_Where
objConn.Execute(strSQL)
Delete=True
End Function
‘返回单条数据
Public Function ReturnSingle()
If objDict.Item(KeysArray(0,0))="" Then Call ShowError(ErrorMsg,02) :Exit Function
SQL_Start="Select * From "& Table
SQL_Where=" Where "& KeysArray(0,0) &"="& objDict.Item(KeysArray(0,0))
strSQL=SQL_Start & SQL_Where
Set objRS =objConn.Execute(strSQL)
If objRS.EOF or objRS.BOF Then
Call ShowError(ErrorMsg,03)
Else
For i=1 To Ubound(objDict.Items)-1
objDict.Item(KeysArray(i,0)) = objRS(i)
Next
End IF
Set objRS =Nothing
ReturnSingle=objDict
End Function
‘返回分页数据
‘需要继承回传的数据
Public Function ReturnList()
‘必须指定页长、页数
If PageSize="" Then Call ShowError(ErrorMsg,0) :Exit Function
End Function
Public Function Transfer(ExternalDict)
Set objDict=ExternalDict.objDict
‘参数导入,只是为了书写方便
Table=ExternalDict.Table
KeysArray=ExternalDict.KeysArray
ItemArray=objDict.Items
End Function
Private Sub Class_Initialize()
ErrorMsg="DB"
‘传入FormDriver处理过的Dictionary
End Sub
Private Sub Class_Terminate()
‘返回FormDriver处理过的Dictionary
End Sub
End Class
‘******************************************************
‘******************************************************
‘底层B:对Dictionary操作的封装。
‘返回错误代码头:DC
‘******************************************************
Class TDictionaryDriver
Public Table
Public KeysArray
Public objDict
Private Key
Private Item
Private ErrorMsg
‘根据系统缓存导入框架
‘报错信息
Public Function Creat()
‘必须指定数据表
If Table="" Then Call ShowError(ErrorMsg,01) :Exit Function
‘必须是系统缓存中已经存在的数据表
If IsNull(application(Table)) Then Call ShowError(ErrorMsg,02) :Exit Function
‘导入数据表框架
KeysArray=application(Table)
End Function
‘根据数据表框架-获取[过滤]数据
‘通过加密的方案解决表单字段和数据库字段的异步问题
Public Function GetRequest()
for i=0 to Ubound(KeysArray)-1
Key=KeysArray(i,0)
Item=Request(md5(Key))
‘Item=Request.QueryString(md5(Key))
‘Item=Request.Form(Key)
objDict.Add Key,Item
next
‘形成Dictionary对象
GetRequest=True
End Function
‘根据数据表框架-效验获取的数据
Public Function Valid()
‘注入转换和过滤
‘必填项
If objDict.Item(KeysArray(0,0))="" Then
‘对于新增数据,必填项目不能为空
‘允许更新操作跳过必填项目遍历进行部分更新
for i=1 to Ubound(KeysArray)-1 ‘跳过主键遍历
If Trim(KeysArray(i,2))="No" And objDict.Item(KeysArray(i,0))="" Then Call ShowError(ErrorMsg,03) :Exit Function
next
End IF
‘字段类型要求
for i=0 to Ubound(KeysArray)-1
‘效验数据类型要求
If KeysArray(i,1)="int" Then
If IsNumeric(objDict.Item(KeysArray(i,0)))=0 Then Call ShowError(ErrorMsg,04) :Exit Function
If objDict.Item(KeysArray(i,0))>2147483647 or objDict.Item(KeysArray(i,0))<-2147483647 Then Call ShowError(ErrorMsg,05) :Exit Function
ElseIf objDict.Item(KeysArray(i,0))<>"" And KeysArray(i,1) ="datetime" Then
If IsDate(objDict.Item(KeysArray(i,0)))=0 Then Call ShowError(ErrorMsg,06) :Exit Function
ElseIF KeysArray(i,1)="bit" Then
If (Not objDict.Item(KeysArray(i,0))=0) And (Not objDict.Item(KeysArray(i,0))=1) Then Call ShowError(ErrorMsg,07) :Exit Function
End If
‘效验字段长度
If IsNumeric(KeysArray(i,4)) And Len(objDict.Item(KeysArray(i,0)))>=KeysArray(i,4) Then Call ShowError(ErrorMsg,08) :Exit Function
‘默认值
next
Valid=True
End Function
‘从数据库框架和Dictionary还原出完整的表单,该表单需要具体对象类根据实际需求进行进一步处理
‘通过加密的方案解决表单字段和数据库字段的异步问题
Public Function ReturnForm()
Dim strForm
strForm="
    " &chr(10)
    strForm=strForm &"
  • " &chr(10)
    for i=0 to Ubound(KeysArray)-1
    ‘效验数据类型
    If KeysArray(i,1)="int" Then
    ‘Radio
    ‘Select
    ‘Checkbox
    strForm=strForm &"
  • "&chr(10)
    ElseIf KeysArray(i,1) ="datetime" Then
    strForm=strForm &"
  • "&chr(10)
    ElseIF KeysArray(i,1)="bit" Then
    strForm=strForm &"
  • "&chr(10)
    ElseIF KeysArray(i,1)="text" Then
    strForm=strForm &"
  • "& objDict.Item(KeysArray(i,0)) &"
  • "&chr(10)
    End If
    next
    strForm=strForm &"
" &chr(10)
Response.Write strForm
ReturnForm=True
End Function
Private Sub Class_Initialize()
‘创建Dictionary对象
Set objDict=CreateObject("Scripting.Dictionary")
ErrorMsg="DC"
End Sub
Private Sub Class_Terminate()
‘释放Dictionary对象
Set objDict=nothing
End Sub
End Class
‘******************************************************
‘交互层,根据实际需要定制结合对Dictionary和DataBase的操作,定义针对对象的直接操作。
‘返回错误代码头:UR
‘******************************************************
Class TUser
Public Table
Private objDictionary
Private objDataBase
Private ErrorMsg
Public Function Update()
iF objDataBase.Update Then Update=True
End Function
Public Function Delete()
iF objDataBase.Delete Then Delete=True
End Function
Public Function DrawForm()
iF objDictionary.ReturnForm Then DrawForm=True
End Function
Public Function ValidAndTransfer()
objDictionary.GetRequest()
If objDictionary.Valid Then
Call objDataBase.Transfer(objDictionary)
Else
Call ShowError(ErrorMsg,01) :Exit Function
End If
End Function
Public Function Creat()
If Not Table="" Then
objDictionary.Table=Table
objDictionary.Creat()
End If
Creat=True
End Function
Private Sub Class_Initialize()
ErrorMsg="UR"
Set objDictionary= new TDictionaryDriver
Set objDataBase = new TDBDriver
End Sub
Private Sub Class_Terminate()
Set objDictionary= Nothing
Set objDataBase = nothing
End Sub
End Class
‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
Call System_Initialize()
Dim objUser
Set objUser = new TUser
objUser.Table="Comm_User"
If objUser.Creat Then
‘objUser.ValidAndTransfer()
‘objUser.Update()
Call objUser.DrawForm()
End IF
Set objUser = nothing
Call System_Terminate()
‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
%>
发表评论: 昵称 * 网站 记住我
正文* (留言最长字数:1000)

◎且以我微薄的力量,捍卫你更加微薄的说话的权利。

返回页首
有0个引用
有16个评论
.sss sss 8/21/2005 5:14:04 PM fdsfasdfdsfdsfdsfasdfdsafdsafdsafdasfdasfdsafdsf
.skyblue 8/18/2005 12:22:06 AM 我本来在仿照Z-BLOG的架构在写一个系统,发现其中的USER类,Category类等,很多地方都是类似的,都是一些对数据库CIUD的操作,我就想,是不是可以再抽象出一个数据库操作类来,让实现业务的类来调用。在你这边看到了一些希望。呵呵。
BTW:能不能给份可以运行的范例看看,
你这BLOG样式改了,在这上面看代码,犯晕的说。
.aether 8/17/2005 8:38:59 PM 对数据库除了有与表单交互得到数据,还需要根据参数得出数据并显示的部分
这一部分我不明白你所指的具体问题,如果是说从数据库中还原表单,你可以参考Dictionary类的DrawForm()方法;
当外部提交某张表单时,从对应的全局数组中生成相应的Dictionary对象
这一部分的实现有几个步骤,都在Dictionary类中。
首先,程序抓取到表单的提交动作(Action),然后根据这个动作激活底层驱动;
然后在字典驱动中,通过Creat()方法获取对应表单在appliction中的数组缓存,其中指定表单的参数是通过在业务逻辑的类自定义传入的,而这些映射着表及其字段的二维数组是在整个程序启动的时候遍历扫描到全局变量中的;
然后通过GetRequest()方法,依次遍历这个表的每一个字段(这里表现为遍历数组),并且把抓取到数据的字段新建为Dictionary对象,即:ObjDictionary.Add Key,Item。
其后的处理有很多变化,一般是先用ValidTpye()方法遍历和验证抓取到的数据类型,ValidFill()方法验证是否为必填项目等等,最后交给数据访问层组合SQL语句入库。
匆匆一说,不知道解释清楚没有,这个框架我还在不断修缮和改进,还是等到可以见人的时候再拿出来吧:)
.skyblue 8/17/2005 7:52:16 PM 这些天一直在考虑的问题回头在你这边一看,似乎找到了一个比较合理的解决办法,
照你这样子,对于如USER类,NEWS类之类的实现具体业务逻辑的类中将不出现SQL语句,它们的实例获取的表单数值将全部转由数据库驱动层来进行数据库交互,是这样么?
只是对数据库除了有与表单交互得到数据,还需要根据参数得出数据并显示的部分,这部分的解决没有给出。。
思路算是理顺了,技术上又不行了,残念。。
我不明白你说的
"当外部提交某张表单时,从对应的全局数组中生成相应的
Dictionary对象"这个具体是怎样做的,8过你恐怕没空给我解释那么多,不知道有没有一些更完整的示例可以看呢?
.烟灰 7/11/2005 6:47:41 AM www.xyforever.org/ash/
可以做个链接吗?
QQ:1658150
可以的话 倒blog留个言吧?
.我佛山人 我佛山人 7/8/2005 9:39:10 PM 发过在这里了
http://www.flash8.net/bbs/dispbbs.asp?boardID=20&ID=247879
.Aether 7/8/2005 10:02:27 AM 服务端验证类不是有了么?
ASP和PHP的都放出了,基于XML的2.0Beta也放出来了啊。
你去blueidea搜索一下就可以了。
.skyblue 7/8/2005 3:03:01 AM 我佛山人
前辈的说.
爱4你的表单验证类了.
什么时候有空写个服务端验证类啊.
.Aether 7/7/2005 4:14:02 PM 汗阿汗,忽然想起来前两天研读的表单验证类正是你写的,还在琢磨怎么才能抄袭过来呢~~
.Aether 7/7/2005 8:59:32 AM 是这个意思,不过看上去也已经到ASP脚本代码的极限了。可以分享关键思路么?
.我佛山人 我佛山人 7/6/2005 11:45:10 PM 我的做法是根据数据库结构,生成数据模型层、数据访问层和商业逻辑层的代码,现在已经实现到数据访问层了,商业逻辑层上用我的表单验证类严格控制输入
已经应用在两个小项目中,表现不错
.archey 7/6/2005 12:02:17 AM 严重关注中.
\PS,你是想把我的眼睛也搞成你那样,陪你啊
.Aether 7/5/2005 7:27:02 PM 别阿……都还在测试中呢……
.Duncan Duncan 7/5/2005 6:32:26 PM 呵呵 真的太小了 收了
.rainbowsoft 6/28/2005 1:07:30 AM 框里的字有点小了.
.cardso 6/27/2005 9:58:07 PM 收藏!