将logging集存储为一个类的实例?

有以下情况。 我有几个表单,基本上有几个dropboxes,列表等。我用ms sql db的logging填充他们。 但是,是否有一种方法只查询数据库一次,并在应用程序的整个生命周期中将这些logging存储为一个类的实例,而不是每次用户打开表单时都要查询。

连接是这样的:

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 

有人可以为我提出一个解决scheme吗? 我可以看到所有来自交通繁忙的问题,而且几乎是不必要的

如果您只想让logging集可用,请在标准模块中将该variables变为公共variables

 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 

现在Rs将在项目的任何地方都可用。 你可以在需要的时候运行connection_test,如果logging集closures,它会创build它。 如果没有,你很好走。

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

例如,假设我有一个Access表:

  ClientID, Autonumber ContactFirst, String ContactLast, String Company, String CityState, String Volume, Double 

我创build一个CClient类与我的表中的每个字段的属性。 我也创build一个CClients类来容纳所有的CClient实例。 在标准模块中,你可能有这样的东西

 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中

 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中

 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实例,创build一个UPDATE sql语句并执行它。 你需要在CClient中实现某种IsDirty属性,以便只更新那些改变了的东西。 其余的CClient和CClient是基本类模块的东西。

您可以调用WriteToDB很多或一些。 在某些应用程序中,只要发生了一些变化就可以写出来 在其他情况下,我只在工作簿closures时才回写数据库。 它的种类取决于你的应用程序的stream程。 真正的美妙之处在于,如果您从Access数据库更改为文本文件进行数据存储,则只需切换到CClient中的方法即可。 所有其余的代码都会消耗C客户端,而不关心数据的存储位置。

你可以在这里看到工作簿和Access数据库http://www.dailydoseofexcel.com/excel/ClientClassExample.zip

在这里阅读Disconnected Recordsets。

文章所做的一件事包括(在示例代码中),但不强调的是,您必须使用adLockBatchOptimistic 。 您不必使用adOpenForwardOnly一样使用adOpenForwardOnly 。 而且,当然,你的Recordset对象必须在子之外有一个作用域。 我会这样做:

 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 

当然你想添加error handling;)。 然后在调用代码中声明一个Recordset对象,并通过调用Function来实例化它。