ASP的数据库类

一、前言
  提到ASP操作数据库,大多数人会想到:共用的连接字串ConStr、Conn.Open ConStr建立数据库连接、Conn.Execute SqlCmd方式执行命令、RecordSet.Open Sql,Conn,1,1取得记录集,的确这种方法被99%的人或公司采用。对于操作数据库过程中产生的错误,恐怕99%的人不会进行处理,要么在程序的开头加入on error resume next“轻松”跳过去、要么让错误信息连同错误代码一同“暴尸”在浏览者面前。对于前一种情况可能会产生让人莫明其妙的怪异结果,后一种情况,可能会在某个时间(比如连接数据库时)暴露您的敏感信息,影响网站安全。当然,还是有个别负责的程序员同志会在容易产生错误的操作后面加入if err.xxxx来处理可能的错误,但这似乎不是一个好办法,一不小心就可能漏掉了。
  我至今也没有想明白,为什么在VB和ASP.NET中都存在的On Error Goto,偏偏在ASP中被取消了。
  另外不得不提的是,当您在前面使用on error resume next而在后面不想resume next了,对不起,没办法,您只能把它“贯彻到底”。看看其它语言的异常机制,try..catch..finally随心所欲,真是爽酷了!

  说了这么多,并不要为ASP引入诸如异常机制等新的内容,毕竟ASP语言本身也决定这是不可能实现的(ASP.NET中实现了),只是想在ASP中最普遍的也是最容易出现错误的数据库操作中,找到一种有效的错误处理方式,并把conn、RecordSet等封装起来,达到最大限度的精简。于是便有了下面的数据库类。


二、数据库类
1、功能
  正如前面所说,这个类的目的是把ADODB.Connection、Adodb.Recordset等烦琐的操作封装起来并在类里实现错误处理。现在看看类的成员、属性和方法:
  1)成员:(没有公有或保护成员)
  2)属性:
    ClassName-返回类名
    Version-返回版本
    LastError-返回最后的错误
    IgnoreError-设置/返回是否忽略数据库错误
    Connection-返回连接对象(ADODB.Connection)
    ConnectionString-设置/返回连接字串(本示例为SQL Server,如为其它请根据实际设定)
    FieldCount、PageSize、PageCount、AbsolutePage、AbsolutePosition、Bof、Eof-请参考Adodb.Recordset相应内容
  3)方法:
    Setup-设置连接数据服务器的帐号、密码、数据库名、主机/IP
    Connect-连接数据库
    Close-关闭数据库连接并释放资源
    Query-执行数据库查询命令并返回数据集
    ExeSQL-执行SQL命令(不返回数据库)
    FieldName-返回指定序号的字段名
    Fields-返回指定的(序号或字段名)字段的值
    Data-同上
    MoveNext、MovePrevious、MoveFirst、MoveLast-请参考Adodb.Recordset相应内容


2、实现代码(DBSql.inc.asp)

内容太长,点击此处打开/折叠...
<%
'========================================================================
' CLASS NAME:  clsDB
' DESIGN BY :    彭国辉
' DATE:              2003-12-18
' SITE:               http://kacarton.yeah.net/
' Blog:               http://blog.csdn.net/conch
' EMAIL:             [email protected]
' MODIFY:
'   2004-6-25: 升级后的数据引擎,返回错误代号小于0(也可以是ASP对数值的
'              定义有变),修改错误检测err.number>0 ==> err.number<>0
'   2004-6-30:修改错误处理,忽略如游标类型改变等非错误性质的提示
'
'文章为作者原创,转载前请先与本人联系,转载请注明文章出处、保留作者信息,谢谢支持!
'========================================================================

 

Class clsDB

  ' name of this class
  ' var string
  ' @access    Private
  ' @see       property: Name
  Private m_strName

  ' version of this class
  ' var string
  ' @access    Private
  ' @see       property: Version
  Private m_strVersion

  ' Error Object
  ' @var ADODB.Connection.Errors
  ' @access    private
  ' @see       property: LastError
  Private m_LastError
 
  ' Ingore all Connection.Errors
  ' var Boolean
  ' @access    private
  ' @see       property: IgnoreError
  Private m_IgnoreError

  ' Connection Object
  ' var ADODB.Connection
  ' @access    Private
  ' @see       property: Connection
  Private m_Connection
 
  ' Is connection to database?
  ' var boolean
  ' @Private
  Private m_bIsConnect

  ' RecordSet
  ' var RecordSet
  ' @access    Private
  Private m_RecordSet

  ' Connection string
  ' var string
  ' @access    Private
  ' @see       property: ConnectionString
  Private m_ConneStr

  ' Database server host name or IP
  ' var string
  ' @access    Private
  ' @see       property: Host
  Private m_strHost

  ' Database name
  ' var string
  ' @access    Private
  ' @see       property: Database
  Private m_strDatabase

  ' Account to connection database
  ' var string
  ' @access    Private
  ' @see       property: UserName
  Private m_UserName

  ' Password to connection database
  ' var string
  ' @access    Private
  ' @see       property: Password
  Private m_Password

  ' get class name attribute.
  ' usage: oTemplate.Name
  ' access    public
  Public Property Get ClassName()
    ClassName = m_strName
  End Property

  ' get class version attribute.
  ' usage: oTemplate.Version
  ' access    public
  Public Property Get Version()
    Version = m_strVersion
  End Property
 
  ' Get class last error messages.
  ' usage: oTemplate.LastError
  ' @access    public
  Public Property Get LastError()
    LastError = m_LastError
  End Property
 
  ' Get or Set Ignore connection.errors
  Public Property Get IgnoreError()
    IgnoreError = m_IgnoreError
  End Property
 
  Public Property Let IgnoreError(ByVal Value)
    m_IgnoreError = Value
  End Property
 
  ' Get Connection
  Public Property Get Connection()
    Connection = m_Connection
  End Property
 
  ' Get connection string
  Public Property Get ConnectionString()
    ConnectionString = m_ConneStr
  End Property
 
  ' Set connection string
  Public Property Let ConnectionString(ByVal Value)
    m_ConneStr = Value
  End Property
 
  ' Get data fields count
  Public Property Get FieldCount()
    FieldCount = m_RecordSet.Fields.Count
  End Property
 
  ' Get RecordSet PageSize
  Public Property Get PageSize()
    on error resume next
    PageSize = m_RecordSet.PageSize
    if err.number<>0 then ShowError("Can not get PageSize!")
  End Property
 
  ' Set RecordSet Page Size
  Public Property Let PageSize(ByVal Value)
    on error resume next
    m_RecordSet.PageSize = Value
    if err.number<>0 then ShowError("Can not set PageSize to " & Value)
  End Property
 
  ' Get RecordSet page count
  Public Property Get PageCount()
    PageCount = m_RecordSet.PageCount
  End Property
 
  ' Get RecordSet record count
  Public Property Get RecordCount()
  on error resume next
    RecordCount = m_RecordSet.RecordCount
    if err.number<>0 then ShowError("Get RecordCount error.")
  End Property
 
  ' Get RecordSet Absolute Page
  Public Property Get AbsolutePage()
    on error resume next
    AbsolutePage = m_RecordSet.AbsolutePage
    if err.number<>0 then ShowError("Can not get AbsolutePage!")
  End Property
 
  ' Set RecordSet Absolute Page
  Public Property Let AbsolutePage(ByVal Value)
    on error resume next
    m_RecordSet.AbsolutePage = Value
    if err.number<>0 then ShowError("Can not set AbsolutePage to " & Value)
  End Property
 
  ' Get RecordSet Absolute Position
  Public Property Get AbsolutePosition()
    on error resume next
    AbsolutePosition = m_RecordSet.AbsolutePosition
    if err.number<>0 then ShowError("Can not get AbsolutePosition!")
  End Property
 
  ' Set RecordSet Absolute Position
  Public Property Let AbsolutePosition(ByVal Value)
    on error resume next
    m_RecordSet.AbsolutePosition = Value
    if err.number<>0 then ShowError("Can not set AbsolutePosition to " & Value)
  End Property

  ' Bof
  Public Property Get Bof()
    Bof = m_RecordSet.Bof
  end Property
 
  ' Eof
  Public Property Get Eof()
    Eof = m_RecordSet.EOF
  end Property
   
  'Setup the databease host name, database name, User name(account), password
  Public Sub Setup(Account, Password, Database, Host)
    m_UserName = Account
    m_Password = Password
    if Database<>"" then m_strDatabase = Database
    if Host<>"" then m_strHost = Host
    m_ConneStr = "Driver={SQL Server};Server=" & m_strHost & ";Database=" &_
                 m_strDatabase & ";Uid=" & m_UserName & ";Pwd=" & m_Password & ";"
  End Sub
 
  ' Connect to database
  Public Function Connect()
    on error resume next
    m_Connection.Open m_ConneStr
    if err.number<>0 Then ShowError("数据库连接错误:(Server:" & m_strHost & ", Database:" & m_strDatabase & ")")
    m_bIsConnect = true
    Connect = true  'todo://
  end Function
 
  ' Diconnect database
  Public Function Close()
    on error resume next
    Set m_RecordSet = Nothing
    Set m_Connection = Nothing
    m_bIsConnect = false
    Close = true
    if err.number<>0 then ShowError("切断数据库连接时出错")
  end Function
 
  ' Query
  Public Sub Query(SQLCommand)
    on error resume Next
    if not m_bIsConnect then Connect
    Set m_RecordSet = Server.CreateObject("Adodb.Recordset")
    'Set m_RecordSet = m_Connection.Execute(SQLCommand)
    m_RecordSet.Open SQLCommand, m_Connection, 1, 1
    if err.number<>0 then ShowError(SQLCommand):exit sub
    if m_Connection.Errors.Count>0 And m_IgnoreError=false then ProcessError(SQLCommand)
  End Sub
 
  ' ExeSQL Command
  Public Sub ExeSQL(SQLCommand)
    on error resume Next
    if not m_bIsConnect then Connect
    m_Connection.Execute SQLCommand
    if err.number<>0 then ShowError(SQLCommand):exit sub
    if m_Connection.Errors.Count>0 And m_IgnoreError=false then ProcessError(SQLCommand)
  End Sub
 
  ' Get Fields Name
  Public Function FieldName(ByVal FieldId)
    on error resume next
    FieldName = m_RecordSet.Fields(FieldId).Name
    if err.number<>0 then ShowError("不能读取字段" & FieldID & "名称!")
  End Function
 
  ' Get fields data
  Public Function Fields(ByVal FieldId)
    on error resume next
    Fields = m_RecordSet.Fields(FieldId)
    if err.number<>0 then ShowError("不能读取字段" & FieldID & "数据!")
  End Function
 
  ' Get fields data
  Public Function Data(ByVal FieldId)
    on error resume next
    Data = m_RecordSet.Fields(FieldId)
    if err.number<>0 then ShowError("不能读取" & FieldID & "数据!")
    'if m_Connection.Errors.Count>0 then ShowError("不能读取" & FieldID & "数据!")
  End Function
 
  ' Move to next record
  Public Sub MoveNext()
    on error resume next
    if m_bIsConnect then m_RecordSet.MoveNext
    if err.number<>0 then ShowError("MoveNext error")
  End Sub
   
  ' Move to Previous record
  Public Sub MovePrevious()
    on error resume next
    if m_bIsConnect then m_RecordSet.MovePrevious
    if err.number<>0 then ShowError("MovePrevious error")
  End Sub
   
  ' Move to First record
  Public Sub MoveFirst()
    on error resume next
    if m_bIsConnect then m_RecordSet.MoveFirst
    if err.number<>0 then ShowError("MoveFirst error")
  End Sub
   
  ' Move to Last record
  Public Sub MoveLast()
    on error resume next
    if m_bIsConnect then m_RecordSet.MoveLast
    if err.number<>0 then ShowError("MoveLast error")
  End Sub
 
  ' 2004-6-30
  Private Sub ProcessError(ByVal sqltxt)
    for i=0 to m_Connection.Errors.Count-1
      If m_Connection.Errors.Item(i).Number<>0 Then ShowError(sqltxt)
    Next
  End Sub
 
  ' This function is called whenever an error occurs and will handle the error
  ' Additionally the error message will be saved in m_strLastError.
 ' @param     $msg         a string containing an error message
  ' @access    private
  ' @return    void
  Private Sub ShowError(ByVal sqltxt)
    for i=0 to m_Connection.Errors.Count-1
      Response.Write m_Connection.Errors.Item(i) & "(" & m_Connection.Errors.Item(i).Number & ")<br>"
    Next
    m_LastError = Err.Description
   
    m_Connection.Errors.Clear
    Response.Write "<br>------------------------------------------------------<br>" &_
                   "<font color=red size=4>" & sqltxt & "</font>"
'     Response.Write "<br>------------------------------------------------------<br>" &_
'                    "<font color=red size=4>" & Left(sqltxt, 10) & "...(错误信息已被屏蔽),请与网站管理员联系!</font>"
'     Response.End
  End Sub

  ' Class constructor, set class default attributes, you can change it
  Private Sub class_Initialize
    m_strName = "clsDB"
    m_strVersion = "1.0"
    Set m_Connection = Server.CreateObject("ADODB.Connection")
    '请修改此处为你连接数据库的默认值
    Setup "sa", "password", "Northwind", "(local)"
    m_bIsConnect = False
    m_IgnoreError = False
  End Sub

  ' Class destructor, free memory.
  Private Sub class_Terminate
    Set m_RecordSet = Nothing
    Set m_Connection = Nothing
  End Sub

End Class

%>

 


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=42869


<script src="http://localhost:82/PromoteIcon.aspx?id=42869"></script>[ 收藏到我的网摘]   天蝎蝴蝶发表于 2004年07月16日 11:50:00
<link href="http://blog.csdn.net/nhconch/Services/Pingback.aspx" rel="pingback"><script>function hide(){showComment();}</script>
相关文章:
<script type="text/javascript">document.write(" ");</script>  
Estyle(靳田) 发表于2004-07-16 15:22:00  IP: 220.167.102.*
前面“On Error Resume Next”了,后面仍然可以“On Error Goto 0”来悬崖勒马,并非只能贯彻到底。
不得不说,虽然看起来更多地语言采用“Try...Catch”,但“On Error”也不失为一种优秀的异常处理机制。

 
Estyle(靳田) 发表于2004-07-16 15:46:00  IP: 220.167.102.*
另外,我觉得,对于异常处理。如果没有实现事务性,那么异常处理的意义也就小了很多。
还有,对于你的代码,异常处理分布在每个过程里面,不如做一个通用的异常处理页面,理由如下:
1、你的过程内的异常处理只是简单地捕获异常并显示友好错误信息,在修复方面的工作做得不多,意义不大且工作重复;
2、用户似乎不应该看到过多的错误细节。
实现方法大概是,先On Error Resume Next,再在页面末尾用SSI(不推荐)、Server.Execute或者Server.Transfer转到错误信息处理页面,统一进行错误捕获和信息反馈。
我觉得,这个数据库类可能并不太实用,大概看起来就是把Recordset和Connection对象的常用成员组合到了一起……
——这些都只是我个人的一些粗浅认识而已,还请多批评指教。

对了,我觉得对于异常处理,我们可以把重点放在异常修复上。考虑考虑?

 
天蝎蝴蝶 发表于2004-07-16 16:12:00  IP: 61.142.213.*
Estyle(靳田) 说得很有道理,这里面根本没有错误修理,而且错误显示还有很多值得改进的地方。至于在页尾才进行处理的话,可以会将上一个的错误带到后面,而形成一连串的错误,扩大了错误的影响。
这种方法与其他人(包括以往的同事)交流时,大部分也表示不大习惯。这个类只是一个引子,后面的文章会用到它。

 
天蝎蝴蝶 发表于2004-07-16 16:13:00  IP: 61.142.213.*
不知Estyle(靳田) 在异常修复上有什么好的方法的,我目前的思路比较零散。以后多交流!

 
inelm(木野狐) 发表于2004-08-15 09:19:00  IP: 61.171.12.*
>>> 但“On Error”也不失为一种优秀的异常处理机制。

靳田说的大部分我同意,但这句话不赞同的, on error 这种语法已经被证明了是 vb 的一个令人生厌的弱项。 在 vb.net 里面使用了先进的 try.. catch... finally 机制也正说明了这一点。

 
piggybank 发表于2004-11-12 16:06:00  IP: 220.163.28.*
呵呵
On Error Goto MY_ERROR_HANDLER
'Try Start
... ...
'Try End
On Error Goto 0

goto GO_ON

MY_ERROR_HANDLER:
'Catch something
Select Case Err.Number
Case xxxxxx
... ...
Case Else
End Select
... ...

GO_ON:
'Finnaly

完全可以做到类似 Try Catch 的捕获。只不过不那么“优美”而已。

另外,
Dim lngErrorNumber as Long
On Error Resume Next
'Try Start
... ...
'Try End

lngErrorNumber = Err.Number
On Error Goto 0

Select Case lngErrorNumber
Case 0
...
Case xxx
'Handle
...
Case Else
...
End Select

这样的处理结构也不错——与前者相比,比较适合针对一两句代码设置陷阱。

对于开发人员而言,在什么地方设置陷阱,如何处理等等,是一种高级编程策略的体现。至于能力高低因人和经验而异,但没有和有之间的差别意义就不同了。
VB 有错误捕获和处理的能力,VB.Net 在这方面也许更强
个人认为这谈不上VB/VBS的弱项。

 
piggybank 发表于2004-11-12 16:33:00  IP: 220.163.28.*
>我觉得,这个数据库类可能并不太实用,大概看起来就是把Recordset和Connection对象的常用成员组合到了一起……

同感。

if err.number<>0 Then ShowError("数据库连接错误:(Server:" & m_strHost & ", Database:" & m_strDatabase & ")")
m_bIsConnect = true

这一句漏掉了 :Exit Sub(当然,针对ASP可以在ShowError中用 Response.End 来结束,但对于上面的代码而言,逻辑上不完整)

由此想到的题外话:诸如此类的代码,最好不要省事,写为
If .... Then

Else

End If
哪怕中间空着,但逻辑很清楚,也不容易出现人为失误——看你别的代码都有,就这一句漏掉了。

封装函数、类的时候,往往有很多种策略。谈不上究竟哪种好,哪种不好——关键看你选择哪一个 View 了。

比如,既然封装成为一个 Class,那么对于调用者来说,应该由它自己决定如何处理错误——我看到你的代码里有 LastError,那怎么不用上它呢?封装方法和函数的思路有很多种,各有各的好处。我个人比较喜欢类似 COM 的方法的封装:每一个方法都是 Bool 类型。如果返回值为 False,则调用者需要检查 LastErrorNumber(而不是LastErrorMessage,为什么?)
当然,你也可以约定你的调用者用别的方式来调用。比如无论如何都要检查某个 Bool 类型的 Property,或者抛出错误(异常)——Err.RaiseError(Estyle纠正我一下,不记得语法了,我在CoffeeBar)让调用者自行处理,呵呵

题外话,On Error Resume Next 在这一点上有一个很好的作用:消极容错。使用时应该根据逻辑适当分段,否则通篇用一两个 On Error Resume Next,那除非是为了“隐藏错误”,谈不上“错误处理”。

所以,在你的类中,ShowError() 这个方法就有点“越俎代疱”了。不妨采用类似于 IgnoreError 这样的思路,提供标准的、默认的错误处理方式之外,让调用者也可以设置一下错误处理的方式,甚至可以定制 ShowError() 的具体内容——比如 EStyle 说的 SSI、Transfer、Execute等方式。

说到这里,再想想,虽然封装这样一个类的实际意义未必很大,但通过它和你做的其它一些东西合起来提供一个开发框架,调用者只需要按照这个框架开发、定制一下内容,还是很有意义的。
何况,当你的这个开发框架比较成熟之后,可以用程序来生成它们——产生式编程?意义就更加重大了。

呵呵,以前有个同事做了一个软件来生成代码,但我个人不太喜欢他的开发框架和代码。后来自己摸索,但却没时间完成自动生成了。今天刚好见到有个RapidTier的作品,看起来不错,不过是.Net的。但我觉得在VBS这样的语言针对OOP提供“超能力”的领域来摸索这个事情似乎更有挑战性 ^oo^


 
菜鸟1号 发表于2006-03-30 21:09:00  IP: 125.73.50.*
我这也有一个,不过不是很会用。咯咯

<%
Rem =======================================数据库类=====================

Rem 定义类名称
Class jz_DbAccess
Rem ==================使用说明=========================================
Rem = 作用:集成了用数据库工作时使用的常见功能
Rem = 公有变量:Conn Connection对象
Rem = 公有变量:comm Command对象
Rem = 公有变量:param Parameter对象
Rem = 公有变量:rs Recordset对象
Rem = 属性: DbPath 定义Access数据库路径及名称,只写属性。
Rem = 属性: SqlDatabaseName 定义SQL数据库名称,只写属性。
Rem = 属性: SqlUsername 定义SQL数据库用户名称,只写属性。
Rem = 属性: SqlPassword 定义SQL数据库用户密码,只写属性。
Rem = 属性: SqlLocalName 定义SQL数据库服务器名称,只写属性。
Rem = 属性: TableName 定义表名称,只写属性。
Rem = 属性: MeterList 定义表的列名称列表,可加入top 等SQL 语句,只写属性。
Rem = 属性: SortField 定义表Order By排列方式,只写属性。
Rem = 属性: FilterField 定义表 where 过滤方式,只写属性。
Rem = 方法:DbSet(IsSqlDataBase,OpenComm,OpenRs) 定义用Access还是用Sql,并创建Connection对象,Command对象,Recordset对象
Rem = 方法:AddRecord(FieldList,ValueList) 把记录加到数据库里
Rem = 方法:EditRecord(FieldList,ValueList,Primary) 在数据库里更新已有的记录
Rem = 方法:DeleteRecord(Primary) 从数据库里删除记录
Rem = 函数:GetRecord() 在筛选和排序的基础上返回Recordset
Rem = 函数:GetRecords(Primary) 按参数返回记录
Rem = 方法:RsOpen(Sql,CursorType, LockType) 按参数打开游标
Rem = 函数: RsGetRows(Sql,CursorType, LockType) 将 Recordset 对象的多个记录恢复到数组中
Rem = 函数: RsGetString(sql,Cursor_Type, Lock_Type,StringFormat, NumRows, ColumnDelimiter, RowDelimiter, NullExpr)将 Recordset 作为字符串返回。
Rem =========================================================================================

Rem 定义私有变量
Private LocalDbPath,LocalSqlDatabaseName,LocalSqlUsername,LocalSqlPassword,LocalSqlLocalName
Rem 定义私有变量
Private LocalTableName,LocalSortField,LocalMeterList,LocalFilterField,LocalFen
Rem 定义公有变量
Public Conn,comm,param,rs,ConnStr

Rem 使用Initialize事件提供有缺省值的某些属性。
Private Sub Class_Initialize()
LocalFen="{$AddDate}"
End Sub

Rem 设置使用Terminate事件
Private Sub Class_Terminate()
Rem 内置函数 IsObject(expression) 确定表达式expression是否是一个自动对象。
Rem 为自动对象时,将对象变量 Rs 设置为 Nothing,从内存中完全删除,
if IsObject(rs) then set rs = nothing
Rem 为自动对象时,将对象变量 Comm 设置为 Nothing,从内存中完全删除,
if IsObject(comm) then set comm = nothing
Rem 为自动对象时,将对象变量 Conn 设置为 Nothing,从内存中完全删除,
if IsObject(Conn) then set Conn = nothing
End sub

Rem 因为方法是需外部访问的而且没有返回值,故被声明为公有过程
Public Sub close()
Rem 把私有变量LocalMeterList赋值为"*"
LocalMeterList="*"
Rem 把私有变量LocalMeterList赋值为Empty
LocalSortField=Empty
Rem 把私有变量LocalMeterList赋值为Empty
LocalFilterField=Empty
End Sub

Rem Property Let 过程设置属性值。
Public Property Let DbPath(vNewValue)
Rem 私有变量LocalDbPath赋值为属性值
LocalDbPath=vNewValue
End Property


Rem Property Let 过程设置属性值。
Public Property Let SqlDatabaseName(vNewValue)
Rem 私有变量LocalSqlDatabaseName赋值为属性值
LocalSqlDatabaseName=vNewValue
End Property

Rem Property Let 过程设置属性值。
Public Property Let SqlUsername(vNewValue)
Rem 私有变量LocalSqlUsername赋值为属性值
LocalSqlUsername=vNewValue
End Property

Rem Property Let 过程设置属性值。
Public Property Let SqlPassword(vNewValue)
Rem 私有变量LocalSqlPassword赋值为属性值
LocalSqlPassword=vNewValue
End Property

Rem Property Let 过程设置属性值。
Public Property Let SqlLocalName(vNewValue)
Rem 私有变量LocalSqlLocalName赋值为属性值
LocalSqlLocalName=vNewValue
End Property

Rem Property Let 过程设置属性值。
Public Property Let TableName(vNewValue)
Rem 私有变量LocalTableName赋值为属性值
LocalTableName=vNewValue
End Property

Rem Property Let 过程设置属性值。
Public Property Let MeterList(vNewValue)
Rem 私有变量LocalMeterList赋值为属性值
LocalMeterList=vNewValue
End Property

Rem Property Let 过程设置属性值。
Public Property Let SortField(vNewValue)
Rem 私有变量LocalSortField赋值为属性值
LocalSortField=" Order By "&vNewValue
End Property

Rem Property Let 过程设置属性值。
Public Property Let FilterField(vNewValue)
Rem 私有变量LocalFilterField赋值为属性值
LocalFilterField=" where "&vNewValue&" "
End Property

Rem Property Let 过程设置属性值。
Public Property Let Fen(vNewValue)
Rem 私有变量LocalFen赋值为属性值
LocalFen=vNewValue
End Property

Rem 因为方法是需外部访问的而且没有返回值,故被声明为公有过程
Public Sub DbSet(IsSqlDataBase)
Rem 判断参数IsSqlDataBase的值
If IsSqlDataBase = 1 Then
Rem 给公有变量 ConnStr 赋值
ConnStr = "Provider = Sqloledb; User ID = " & LocalSqlUsername & "; Password = " & LocalSqlPassword & "; Initial Catalog = " & LocalSqlDatabaseName & "; Data Source = " & LocalSqlLocalName & ";"
Else
Rem 给公有变量 ConnStr 赋值
ConnStr ="Provider = Microsoft.Jet.OLEDB.4.0;Data Source = " & Server.MapPath(LocalDbPath)
End If

End Sub

Rem 因为方法是不需外部访问的而且没有返回值,故被声明为私有过程
Private Sub Open_Obj(ObjType)
Select Case (ObjType)
Case ("Conn")
Rem 判断是否 不为自动对象时
If Not IsObject(Conn) then
Rem 语句 On Error 当一个错误发生时,这条语句就执行紧靠发生错误语句后面的语句,或者执行紧靠调用进程后面的语句。
On Error Resume Next
Rem 语句 Set 赋予一个变量或一个性质对象引用。当赋予的值为Nothing 时,使obectva 和任何以前指明的对象解除关系。
Set Conn = Server.CreateObject("ADODB.Connection")
Rem 使用连接属性打开数据库连接
conn.open ConnStr
Rem 判断是否发生错误
Rem 任何涉及 ADO 对象的操作都可能产生一个或多个提供者错误。产生错误时,可以将一个或多个 Error 对象置于 Connection 对象的 Errors 集合中。其他 ADO 操作产生错误时,将清空 Errors 集合,并且将新的 Error 对象置于 Errors 集合中
If Err Then
Rem 对 Errors 集合使用 Clear 方法,来删除集合中现有的全部 Error 对象。发生错误时,ADO 将自动清空 Errors 集合,并以基于新错误的 Error 对象填充集合。
err.Clear
Rem 语句 Set 赋予一个变量或一个性质对象引用。当赋予的值为Nothing 时,使obectva 和任何以前指明的对象解除关系。
Set Conn = Nothing
Rem 发送提示
Response.Write "数据库连接出错,请检查连接字串。"
Rem 停止
Response.End
End If
End If
Case ("Comm")
Rem 判断是否 不为自动对象时
if Not IsObject(comm) then
Rem 语句 Set 赋予一个变量或一个性质对象引用。当赋予的值为Nothing 时,使obectva 和任何以前指明的对象解除关系。
set comm=Server.Createobject("ADODB.Command")
Rem 指示指定的 Command 对象当前所属的 Connection 对象。
comm.ActiveConnection=conn
End if
Case ("Rs")
Rem 判断是否 不为自动对象时
If not IsObject(rs) Then set Rs = Server.CreateObject( "ADODB.Recordset" )
ENd Select

End Sub

Rem 因为方法是不需外部访问的而且有返回值,故被声明为私有函数
Private Function FieldListStr(FieldList,ValueList,format_type)

Rem 定义局部变量
Dim ChoppedFieldList,ChoppedValueList
Dim FieldValueList(2)
Dim FieldNum,ValueNum,i,post
Dim Field_str,Str_i,Value_str

Rem 把参数FieldList通过{$jz}断层分割转换为数组,赋值给局部变量ChoppedFieldList
Rem 内置函数 Split(expression[,delimiter[,count[,compare]]]) 把一个字符串分割并转换成数组。
ChoppedFieldList=Split(FieldList,LocalFen)

Rem 把参数ValueList通过{$jz}断层分割转换为数组,赋值给局部变量ChoppedValueList
Rem 内置函数 Split(expression[,delimiter[,count[,compare]]]) 把一个字符串分割并转换成数组。
ChoppedValueList=Split(ValueList,LocalFen)

Rem 把ChoppedFieldList的数组第一维的上边界,赋值给局部变量FieldNum
Rem 内置函数 UBound(arrayname[,dimension]) 返回数组某维的上边界。缺省维数时,为第一维。
FieldNum=UBound(ChoppedFieldList)

Rem 把ChoppedValueList的数组第一维的上边界,赋值给局部变量ValueNum
Rem 内置函数 UBound(arrayname[,dimension]) 返回数组某维的上边界。缺省维数时,为第一维。
ValueNum=UBound(ChoppedValueList)

Rem 判断 局部变量FieldNum与局部变量ValueNum是否相等,不等时,退出函数
if FieldNum<>ValueNum Then Exit Function

Rem 根据局部变量ValueNum,修改局部变量Value_str为二维数组
ReDim Value_str(3,ValueNum)

Rem 为局部变量Str_i赋初始量为0
Str_i=0

Rem 自定义私有过程 Open_Obj
Open_Obj "Conn"

Rem 打开一个将要增加记录的到表的连接
Set Rs = conn.Execute(LocalTableName,,2)

Rem 通过FieldNum进行循环
For i=0 to FieldNum

Rem 通过参数 format_type 给局部变量Field_str以不同的方式赋值
Select Case (format_type)

Case ("Add")

Rem 对局部变量Field_str进行字符串串联
Rem 自定义函数私有Str_add,以传入的三个参数进行字符串转换

Field_str=Str_add(Field_str,ChoppedFieldList(i),",")

Case ("Edit")

Rem 对局部变量Field_str进行字符串串联
Rem Str_add自定义私有函数,以传入的三个参数进行字符串转换
Field_str=Str_add(Field_str,ChoppedFieldList(i)&"=?",",")

ENd Select

Rem 局数变量数组Value_str第一维0赋值
Value_str(0,i)=ChoppedFieldList(i)
Rem 使用Recordset 对象含有由 Field 对象组成的 Fields 集合的Type属性可返回字段的基本特性,赋值给局数变量数组Value_str第一维1
Value_str(1,i)=Rs.Fields(ChoppedFieldList(i)).type
Rem 使用Recordset 对象含有由 Field 对象组成的 Fields 集合的DefinedSize 属性可返回已声明的字段大小,赋值给局数变量数组Value_str第一维2
Value_str(2,i)=rs.Fields(ChoppedFieldList(i)).DefinedSize
Rem 从局部变量数组ChoppedValueList中赋对应的值给赋值给局数变量数组Value_str第一维3
Value_str(3,i)=ChoppedValueList(i)


Next

Rem 使用 Close 方法可关闭 Connection 对象或 Recordset 对象以便释放所有关联的系统资源。
Rs.close

Rem 给局部变量数组FieldValueList赋值
FieldValueList(0)=Field_str
FieldValueList(1)=Value_str
FieldValueList(2)=FieldNum

Rem 局部变量数组FieldValueList的值赋给FieldListStr函数返回值
FieldListStr=FieldValueList
End Function

Rem 因为方法是不需外部访问的而且有返回值,故被声明为私有函数
Private Function Str_add(add_str,Str,char_str)
Rem 判断参数add_str是否为空值
if add_str="" then
Rem 为空时,函数返回值为参数Str
Str_add=str
else
Rem 不为空时,函数返回值为参数add_str&char_str&str
str_add=add_str&char_str&str
end if
End Function

Rem 因为方法是不需外部访问的而且没有返回值,故被声明为私有过程
Private Sub Param_cmd(str_0,str_1)
Rem 创建局部变量
dim i
Rem 通过参数Str_0循环
rem comm.Parameters.Refresh
for i=0 to str_0
Rem 用指定的属性创建新的 Parameter 对象
Rem Param 为公有变量
rem Response.Write(str_1(0,i)&"---"&str_1(1,i)&"---"&str_1(2,i)&"---"&str_1(3,i))

set param=comm.CreateParameter(str_1(0,i),str_1(1,i),&H0001,str_1(2,i),str_1(3,i))
Rem 使用 Append 方法将它们添加到 Parameters 集合

comm.Parameters.Append param
next
rem comm.Parameters.Refresh
End Sub

Rem 因为方法是不需外部访问的而且有返回值,故被声明为私有函数
Private Function str_addNum(Num,str,char_str)
Rem 创建局部变量
Dim i
Rem 通过参数Num循环
For i=0 to Num
Rem 循环进行字符串串联,并赋值给函数返回值
Rem 自定义私有函数Str_add,通过三个参数转换
str_addNum=Str_add(str_addNum,Str,char_str)
Next
End Function

Rem 因为方法是需外部访问的而且没有返回值,故被声明为公有过程
Public Sub AddRecord(FieldList,ValueList)
Rem 创建局部变量
Dim FieldValueList
Rem 判断私有变量LocalTableName是否为空
if (LocalTableName="") then
Rem 设置错误提示信息
Err.Raise vbobjectError+1,"DBAccess Server","TableName 未设置"
Rem 退出Sub 过程
Exit Sub
End if

Rem 通过自定义私有变量FieldListStr获取转换后的数组。
FieldValueList=FieldListStr(FieldList,ValueList,"Add")

Rem 判断FieldListStr是否为数组
If Not IsArray(FieldValueList) Then
Rem 退出Sub 过程
Exit Sub
Else

Rem 自定义私有过程 Open_Obj
Open_Obj "Conn"

Rem 自定义私有过程 Open_Obj
Open_Obj "Comm"

Rem 指示 Command 对象的类型为将 CommandText 作为命令或存储过程调用的文本化定义进行计算。
comm.CommandType=&H0001
Rem 使用 CommandText 属性定义命令(例如,SQL 语句)的可执行文本
comm.CommandText="Insert into "&LocalTableName&" ("&FieldValueList(0)&") values ("&str_addNum(FieldValueList(2),"?",",")&")"

rem Response.Write("Insert into "&LocalTableName&" ("&FieldValueList(0)&") values ("&str_addNum(FieldValueList(2),"?",",")&")")

Rem 调用自定义私有过程Param_cmd,添加到 Parameters 集合
Param_cmd FieldValueList(2),FieldValueList(1)

Rem 执行在对象的 CommandText 属性中指定的查询。如果 CommandText 属性指定按行返回查询,执行所产生的任何结果都将存储在新的 Recordset 对象中。如果该命令不是按行返回查询,则提供者返回关闭的 Recordset 对象。
comm.Execute


end if
End Sub

Rem 因为方法是需外部访问的而且没有返回值,故被声明为公有过程
Public Sub EditRecord(FieldList,ValueList,Primary)
Rem 创建局部变量
Dim FieldValueList
Rem 判断私有变量LocalTableName是否为空
if (LocalTableName="") then
Rem 设置错误提示信息
Err.Raise vbobjectError+1,"DBAccess Server","TableName 未设置"
Rem 退出Sub 过程
Exit Sub
End if

Rem 通过自定义私有变量FieldListStr获取转换后的数组。
FieldValueList=FieldListStr(FieldList,ValueList,"Edit")

Rem 判断FieldListStr是否为数组
If Not IsArray(FieldValueList) Then
Exit Sub
Else

Rem 自定义私有过程 Open_Obj
Open_Obj "Conn"

Rem 自定义私有过程 Open_Obj
Open_Obj "Comm"

Rem 指示 Command 对象的类型为将 CommandText 作为命令或存储过程调用的文本化定义进行计算。
comm.CommandType=&H0001
Rem 使用 CommandText 属性定义命令(例如,SQL 语句)的可执行文本
comm.CommandText="UpDate "&LocalTableName&" set "&FieldValueList(0)&" Where "&Primary

Rem 调用自定义私有过程Param_cmd,添加到 Parameters 集合
Param_cmd FieldValueList(2),FieldValueList(1)

Rem 执行在对象的 CommandText 属性中指定的查询。如果 CommandText 属性指定按行返回查询,执行所产生的任何结果都将存储在新的 Recordset 对象中。如果该命令不是按行返回查询,则提供者返回关闭的 Recordset 对象。
comm.Execute



end if

End Sub

Rem 因为方法是需外部访问的而且没有返回值,故被声明为公有过程
Public Sub DeleteRecord(Primary)
Rem 判断私有变量LocalTableName是否为空
if (LocalTableName="") then
Rem 设置错误提示信息
Err.Raise vbobjectError+1,"DBAccess Server","TableName 未设置"
Rem 退出Sub 过程
Exit Sub
End if

Rem 自定义私有过程 Open_Obj
Open_Obj "Conn"

Rem 执行 Sql 文本
conn.execute("Delete from "&LocalTableName&" where "&Primary)

End Sub

Rem 因为方法是需外部访问的而且有返回值,故被声明为公有函数
Public Function GetRecord()
Rem 判断私有变量LocalTableName是否为空
if (LocalTableName="") then
Rem 设置错误提示信息
Err.Raise vbobjectError+1,"DBAccess Server","TableName 未设置"
Rem 退出函数
Exit Function
End if

Rem 自定义私有过程 Open_Obj
Open_Obj "Conn"


Rem 设置涵数返回值为Recordset对象
set GetRecord=conn.execute("select "&LocalMeterList&" from "&LocalTableName&LocalFilterField&LocalSortField)
End Function

Rem 因为方法是需外部访问的而且有返回值,故被声明为公有函数
Public Function GetRecords(Primary)

Rem 自定义私有过程 Open_Obj
Open_Obj "Conn"

Rem 设置涵数返回值为Recordset对象,参数为Sql文本
set GetRecords=conn.execute(Primary)
End Function

Rem 因为方法是需外部访问的而且没有返回值,故被声明为公有过程
Public sub RsOpen(sql,Cursor_Type,Lock_Type)

Rem 自定义私有过程 Open_Obj
Open_Obj "Conn"

Rem 自定义私有过程 Open_Obj
Open_Obj "Rs"

Rem 打开游标
Rs.Open sql, Conn, Cursor_Type, Lock_Type,&H0001

End sub

Rem 因为方法是需外部访问的而且有返回值,故被声明为公有函数
Public Function RsGetRows(sql,Cursor_Type, Lock_Type,Rows)

Rem 自定义私有过程 Open_Obj
Open_Obj "Conn"

Rem 自定义私有过程 Open_Obj
Open_Obj "Rs"

Rem 打开游标
Rs.Open sql, Conn, Cursor_Type, Lock_Type,&H0001
Rem 当前记录位置是否位于 Recordset 对象的最后一个记录之后,为True时,将 Recordset 对象的多个记录恢复到数组中
if not rs.eof then RsGetRows=rs.GetRows(Rows)
Rem 使用 Close 方法可关闭 Connection 对象或 Recordset 对象以便释放所有关联的系统资源。
rs.close

End Function


Rem 因为方法是需外部访问的而且有返回值,故被声明为公有函数
Public Function RsGetString(sql,Cursor_Type, Lock_Type,StringFormat, NumRows, ColumnDelimiter, RowDelimiter, NullExpr)

Rem 自定义私有过程 Open_Obj
Open_Obj "Conn"

Rem 自定义私有过程 Open_Obj
Open_Obj "Rs"

Rem 打开游标
Rs.Open sql, Conn, Cursor_Type, Lock_Type,&H0001
Rem 当前记录位置是否位于 Recordset 对象的最后一个记录之后,为True时,将 Recordset 作为字符串返回。
if not rs.eof then RsGetString=rs.GetString(StringFormat, NumRows, ColumnDelimiter, RowDelimiter, NullExpr)
Rem 使用 Close 方法可关闭 Connection 对象或 Recordset 对象以便释放所有关联的系统资源。
rs.close
End Function



End Class
%>

3、使用示例
<!--#INCLUDE file="DBSql.inc.asp"-->
<%
Function HTMLEncode(str)
    If IsNull(str) Then HTMLEncode = "(NULL)" _
    Else HTMLEncode = Server.HTMLEncode(str)
End Function

Dim sql, i
Set sql = New clsDB
sql.Connect
sql.ExeSQL("update Customers set Address='中华人民共和国' where ID=1")
sql.Query("select * from Customers")
Response.Write "<table border=1><tr>"
For i=0 To sql.FieldCount-1
    Response.Write "<td>" &  Server.HTMLEncode(sql.FieldName(i)) & "</td>"
Next
Response.Write "</tr>"
While Not sql.Eof
    For i=0 To sql.FieldCount-1
        Response.Write "<td>" & HTMLEncode(sql.Data(i)) & "</td>" '此处可直接用字段名代替i
    Next
    Response.Write "</tr>"
    sql.MoveNext
Wend
Response.Write "</table>"
sql.Close
Set sql = Nothing
%>


三、小结
  这还只是一个比较粗糙的数据库类,还有很多ADODB的特性没有添加在内,而且灵活性也不够。本文旨在为大家提供另一种思路,各位在看完本文后觉得还是有一点收获的话,我就很满足了。
  此外,我的下一篇文章《将ASP查询分页封装起来》中将用到这个类。

 

你可能感兴趣的:(数据结构,sql,sql,server,asp.net,asp)