首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否将记录集存储为类的实例?

是否将记录集存储为类的实例?
EN

Stack Overflow用户
提问于 2011-05-14 02:51:14
回答 2查看 4.2K关注 0票数 4

有以下场景。我有几个表单,基本上有几个下拉框,列表等。我从一个ms sql数据库的记录填充它们。但是,有没有一种方法可以在应用程序的整个生命周期中只查询一次数据库并将记录存储为类的实例,而不是每次用户打开表单时都进行查询?

连接是这样的:

代码语言:javascript
复制
Sub connection_test()

    Dim Cn As ADODB.Connection
    Dim Rs As ADODB.Recordset
    Dim stSQL As String

    stSQL = "SELECT * FROM dbo.Client"

    Set Cn = New ADODB.Connection

    With Cn
        .CursorLocation = adUseClient
        .Open CONNECTION_STRING
        .CommandTimeout = 0
        Set Rs = .Execute(stSQL)
    End With

    Rs.Close
    Cn.Close
    Set Rs = Nothing
    Set Cn = Nothing
End Sub

有人能给我提个解决方案吗?我可以看到交通拥挤带来的所有问题,而且大多数情况下都是不必要的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-05-14 04:42:26

如果只希望记录集可用,请在标准模块中将变量设置为public

代码语言:javascript
复制
Public Rs As ADODB.Recordset

Sub connection_test()

    Dim Cn As ADODB.Connection
    Dim sSQL As String

    If Rs.State = adStateClosed Then
        sSQL = "SELECT * FROM dbo.Client"

        Set Cn = New ADODB.Connection

        With Cn
            .CursorLocation = adUseClient
            .Open CONNECTION_STRING
            .CommandTimeout = 0
            Set Rs = .Execute(sSQL)
        End With
    End If

End Sub

现在,R将在项目中的任何位置都可用。您可以在需要时运行connection_test,如果记录集已关闭,它将创建它。如果没有,你就可以走了。

通常,我的方法是创建自定义类。我将创建一个CClient类,从记录集(或其他地方)填充它,用业务逻辑操作对象,然后将新值写回数据库。这样一来,我的业务逻辑都不依赖于我使用的是ado。我可以切换到文本文件或Excel工作表作为数据存储,而不必担心代码中的所有依赖项。

例如,假设我有一个访问表:

代码语言:javascript
复制
 ClientID, Autonumber
 ContactFirst, String
 ContactLast, String
 Company, String
 CityState, String
 Volume, Double

我创建了一个CClient类,表中的每个字段都有一个属性。我还创建了一个CClients类来保存所有的CClient实例。在标准模块中,您可能会看到如下内容

代码语言:javascript
复制
Public gclsClients As CClients

Sub Main()

    Set gclsClients = New CClients

    'Fill the class
    gclsClients.FillFromRS

    'change some value
    gclsClients.Client(1).Volume = 100

    'write back to the database
    gclsClients.WriteToDB

End Sub

在我改变一个客户端的音量时,你会有更多的代码调用你的用户表单,等等。基本的事情是,加载类,做任何你需要的事情,然后把类数据写回数据库。我不会向您展示所有的类代码,但是在CClients中

代码语言:javascript
复制
Public Sub FillFromRS()

    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim clsClient As CClient

    Const sSQL As String = "SELECT * FROM tblClient"

    Set cn = New ADODB.Connection

    cn.Open msCON
    Set rs = cn.Execute(sSQL)

    If Not rs.BOF And Not rs.EOF Then
        rs.MoveFirst
        Do While Not rs.EOF
            Set clsClient = New CClient
            With clsClient
                .ClientID = rs.Fields("ClientID").Value
                .ContactFirst = rs.Fields("ContactFirst").Value
                .ContactLast = rs.Fields("ContactLast").Value
                .Company = rs.Fields("Company").Value
                .CityState = rs.Fields("CityState").Value
                .Volume = rs.Fields("Volume").Value
            End With
            Me.Add clsClient
            rs.MoveNext
        Loop
    End If

End Sub

此方法从数据库获取数据并填充一堆CClient实例。也是在CClients中

代码语言:javascript
复制
Public Sub WriteToDB()

    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim clsClient As CClient
    Dim sSQL As String

    Set cn = New ADODB.Connection

    cn.Open msCON

    For Each clsClient In Me
        sSQL = BuildUpdateSQL(clsClient)
        cn.Execute sSQL
    Next clsClient

End Sub

Private Function BuildUpdateSQL(clsClient As CClient)

    Dim sReturn As String

    With clsClient
        sReturn = "UPDATE tblClient SET ContactFirst = '" & .ContactFirst & "',"
        sReturn = sReturn & " ContactLast = '" & .ContactLast & "',"
        sReturn = sReturn & " Company = '" & .Company & "',"
        sReturn = sReturn & " CityState = '" & .CityState & "',"
        sReturn = sReturn & " Volume = " & .Volume
        sReturn = sReturn & " WHERE ClientID = " & .ClientID & ";"
    End With

    BuildUpdateSQL = sReturn

End Function

此方法遍历所有CClient实例,创建一条UPDATE sql语句并执行它。您需要在CClient中实现某种类型的IsDirty属性,以便只更新发生更改的客户端。CClients和CClient的其余部分是基本的类模块。

您可以多次或少量调用WriteToDB。在一些应用程序中,每当有什么变化时,我都会写下它。在其他情况下,我只在工作簿关闭时写回数据库。这在某种程度上取决于你的应用程序的流程。真正的好处在于,如果您从Access数据库更改为用于数据存储的文本文件,则只需更改为CClients中的方法。其余的代码都使用CClients,并不关心数据存储在哪里。

您可以在此处查看工作簿和Access数据库http://www.dailydoseofexcel.com/excel/ClientClassExample.zip

票数 5
EN

Stack Overflow用户

发布于 2011-05-14 03:59:44

阅读有关断开连接的记录集here的信息。

本文(在示例代码中)确实包含了一件事,但没有强调您必须使用adLockBatchOptimistic。您不必像他们那样使用adOpenForwardOnly。当然,您的Recordset对象必须在sub之外有一个作用域。我会这样做:

代码语言:javascript
复制
Function connection_test() as ADODB.Recordset

Dim Cn As ADODB.Connection
Dim Rs As ADODB.Recordset

Dim stSQL As String

    stSQL = "SELECT * FROM dbo.Client"
    Set Cn = New ADODB.Connection

    With Cn
        .Open CONNECTION_STRING
        .CommandTimeout = 0
    End With

    With Rs
        .CursorLocation = adUseClient
        .LockType = adLockBatchOptimistic
        .Open stSQL
        Set .ActiveConnection = Nothing 
    End With

    Set connection_test = Rs

    'DON'T Close the Recordset
    'Rs.Close
    Cn.Close
    'Destroying the local instance is fine, though
    Set Rs = Nothing
    Set Cn = Nothing
End Function 

当然,您希望添加错误处理;)。然后在调用代码中声明一个Recordset对象,并通过调用函数来实例化它。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5996415

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档