dcsimg
December 10, 2016
Hot Topics:

Visual Basic 6 Business Objects

  • November 19, 2002
  • By James Limm
  • Send Email »
  • More Articles »

ADO 2.0 provides us with some powerful new capabilities that we can use to help us serialize an object’s data and transfer it from one process to another or across the network from one computer to another. The core of this capability lies with ADO’s support for batch mode updating of a Recordset object. With this capability, ADO is able to not only provide a reference to a Recordset object, but it can actually copy the object’s data from one process to another or from one machine to another – essentially allowing us to pass ADO Recordset objects by value rather than by reference.

Couple the ability to move Recordset objects across the network with ADO 2.0’s support for Recordset objects that are disconnected from any database connection. This means we can create a Recordset object out of thin air – no database required. We can define the columns of data we want to provide, then add or manipulate rows of data at will.

Between these two capabilities, we can use ADO 2.0 to create an arbitrary Recordset object to store any data we’d like and then pass that Recordset from process to process or machine to machine as we choose. ADO takes care of all the details of serializing the Recordset itself, allowing us to simply interact with a Recordset object to view, update or add our data.

Before we can pass a Recordset around our network we need to create it. There are two ways to create a Recordset object for serializing our object’s data – creating the Recordset from a database, or creating a connectionless Recordset through code.

Creating Recordset Objects from Data

The most common way to create a Recordset object is to select some data from a database to be loaded into the object. However, if we’re going to pass that Recordset around the network we do need to take some extra steps as we open it.

In particular, we need to set the CursorLocation property of our Connection or Recordset object must be set to adUseClient. This causes ADO to use a cursor engine located on the client machine rather than one within the database server itself. Since the cursor engine is local to the client, we can send the Recordset’s data to any machine where ADO or ADOR (the light-weight client version of ADO) is installed.

We also need to specify the LockType property of our Recordset as adLockBatchOptimistic. This causes ADO to build our Recordset object in a batch update mode, allowing us to manipulate the Recordset and its data even if it is not currently connected to the data source.

By setting these two properties as we initialize our Recordset object we will cause ADO to automatically support batch processing of our data, and to automatically pass the Recordset object’s data to any process that interacts with the object.

There is one caveat to this approach. Our CursorType property can only be one of adOpenKeyset or adOpenStatic when we are using a batch mode Recordset. If we are passing the Recordset to a machine that only has ADOR installed (such as a thin client workstation), then we can only use the adOpenStatic setting for the CursorType property.

Let’s take a look at some code that opens a Recordset and returns the object upon request:

Public Function GetData() As Recordset
Dim rs As Recordset
Dim strConnect As String
Set rs = New Recordset
strConnect = "Provider=Microsoft.Jet.OLEDB.3.51;" & _
"Persist Security Info=False;Data Source=D:vb6video.mdb"
With rs
.CursorLocation = adUseClientBatch
.Open "select * from customer", strConnect, adOpenStatic, _
adLockBatchOptimistic
End With
Set GetData = rs
Set rs = Nothing
End Function

This code doesn’t look much different than what we’d expect to see any time we open a Recordset based on some data in a database. However, there are a couple interesting things to note. First off, before calling the Open method we set the CursorLocation property of the object:

.CursorLocation = adUseClientBatch

Then, in the call to the Open method we set the LockType to adLockBatchOptimistic. We also set the CursorType to adOpenStatic. We could have set it to adOpenKeyset if we’d chosen, but by choosing adOpenStatic we know we can pass the Recordset to a client that might only have ADOR installed without having ADO convert our cursor type during that process

Creating a Connectionless Recordset

While we can create Recordset objects from a database, that often won’t work well for serializing data from our objects. It is not at all unusual for an object’s state to include information that isn’t necessarily stored in a database. For instance, we may wish to pass a flag indicating whether our object is new or other types of information between our client workstation and the application server. If our Recordset object is generated directly from a database query we are restricted to only passing information that comes from that database.

Fortunately ADO 2.0 provides a very elegant solution to this problem by allowing us to create a Recordset object that is totally unrelated to any data source. The steps involved in this process are quite straightforward:

  • Create the Recordset object
  • Add columns to the Recordset using the Fields object’s Append method
  • Open the Recordset
  • Add or manipulate data in the Recordset

As an example, the following code creates a connectionless Recordset with two columns of data: Name and BirthDate. We then add a couple rows of information to the Recordset object and return it as a result of the method:

Public Function MakeData() As Recordset
Dim rs As Recordset
Set rs = New Recordset

With rs
.Fields.Append "Name", adBSTR
.Fields.Append "BirthDate", adDate
.Open
.AddNew
.Fields("Name") = "Fred"
.Fields("BirthDate") = "1/1/88"
.Update
.AddNew
.Fields("Name") = "Mary"
.Fields("BirthDate") = "3/10/68"
.Update
End With

Set MakeData = rs
Set rs = Nothing

End Function

The first couple lines simply declare and create an instance of a Recordset object. Once that’s done we can move on to adding columns to the empty Recordset by calling the Append method of the Fields object:

.Fields.Append "Name", adBSTR
.Fields.Append "BirthDate", adDate
After we have columns defined, all that remains is to load our object with some data. This is as simple as calling the AddNew method, loading some data and calling Update to store the data into the Recordset. Of course the data isn’t stored into any database, since this Recordset exists only in our computer’s memory.

Passing a Recordset by Value

We’ve now looked at two different ways to create a Recordset object that we can pass to another process or across the network. Both of the routines shown above are written as Function methods, returning the Recordset object as a result.

ADO itself handles all the details of moving the Recordset object’s data to the client process or computer, so we really don’t need to do any extra work at all beyond setting the properties as we did to create the Recordset. Our client code can be quite simple as shown by the following fragment:

Dim objServer As Object
Dim rs As Recordset
Set objServer = CreateObject("MyDataServer.DataMaker")
Set rs = objServer.GetData
Set objServer = Nothing

Once this code fragment is complete, we have a Recordset object to work with. This code assumes that the code to create the Recordset is in an ActiveX server named MyDataServer and in a class named DataMaker. This ActiveX server could be running in another process, or on another machine on the network.

Regardless, once we’ve got the Recordset through this code, the MyDataServer ActiveX server can be totally shut down – the machine it is running on could even be shut off – and our code can still continue to work with the Recordset and its data.

The program running this code fragment does require a reference to either the ADO or ADOR library in order to function. In many cases the lighter-weight ADOR library is sufficient, as it provides basic support for interacting with Recordset object’s that are created and updated by another process or machine.

PropertyBag Objects

A property bag is an object that supports the concept of a key-value pair. The idea is that the property bag can store a value associated with a key, or name, for that value. For instance, we might store the value 5 along with the key Height. At any point we can also retrieve the Height value from the property bag.

Visual Basic 5.0 introduced the concept of a PropertyBag object as part of the ability to create ActiveX controls. While the concept was useful when storing properties of our control that the developer set at design time, we couldn’t take advantage of the PropertyBag object outside of control creation.

Visual Basic 6.0 extends the PropertyBag object such that we can use it anywhere we choose within our applications. Basically, anywhere that we need to manage key-value pairs, we can make use of the PropertyBag object provided by Microsoft.

Better still, the PropertyBag object implements a Contents property that allows us to access the entire contents of the object as a single Byte array – essentially it provides built-in support for streaming its own data. We can retrieve the data, send the Byte array as a parameter to another process or across the network, and then place it into a PropertyBag object, giving us an exact duplicate of the object we started with.

Of course Byte arrays aren’t nearly as easy to manipulate or work with as a String variable would be. Fortunately this isn’t a serious problem either, as Visual Basic makes it very easy for us to convert a Byte array to a String and then back to a Byte array.

Serializing an Object’s Data

Let’s take a look at some simple code that illustrates how we can use a PropertyBag to serialize the data in an object.

Suppose we’ve got an object with two pieces of data: Name and BirthDate. We can store this data in a PropertyBag object with code similar to this:

Public Function GetObjectData() As String
Dim pbData As PropertyBag
Set pbData = New PropertyBag

With pbData
.WriteProperty "Name", mstrName
.WriteProperty "BirthDate", mdtBirthDate
End With

End Function

Once we’ve created the PropertyBag object, we can simply use its WriteProperty method to store the values from our object into the property bag. In this case, we’re assuming that the name and birth date data are stored in the variables mstrName and mdtBirthDate.

After our property bag has our object’s data, we can retrieve all the data in a single Byte array using the PropertyBag object’s Contents property.

Public Function GetObjectData() As String

Dim pbData As PropertyBag

Set pbData = New PropertyBag

With pbData
.WriteProperty "Name", "Fred"
.WriteProperty "BirthDate", "5/14/77"
End With

GetObjectData = pbData.Contents

End Function

With this simple code we’ve converted our object’s data into a single String variable that we can easily pass as a parameter to another object, even across the network.

Deserializing an Object’s Data

Now that we’ve seen how we can take data from an object and use a PropertyBag to serialize that data into a simple String variable, let’s take a look at how we can use that String variable to load another object with the data.

Since we know we’ll be receiving a String value, the first step is to convert that String into a Byte array so we can place it into the PropertyBag object’s Contents property. While we’re doing this, we’ll also need to create a PropertyBag object to work with:

Public Sub LoadObject(StringBuffer As String)
Dim arData() As Byte
Dim pbData As PropertyBag
Set pbData = New PropertyBag
arData = StringBuffer
pbData.Contents = arData
End Sub

Once we’ve converted the String to a Byte array, we simply set the Contents property of our PropertyBag using that value. This causes the PropertyBag object to contain the exact data that was contained in the other PropertyBag object that we used to create the String variable.

Now that the PropertyBag object has been populated we can use the ReadProperty method to retrieve the individual data values for use by our object:

Public Sub LoadObject(StringBuffer As String)
Dim arData() As Byte
Dim pbData As PropertyBag
Set pbData = New PropertyBag
arData = StringBuffer
pbData.Contents = arData
With pbData
mstrName = .ReadProperty("Name")
mdtName = .ReadProperty("BirthDate")
End With
End Sub

In many ways the use of a PropertyBag object for serializing our object’s data is comparable to how we used the LSet command to convert a UDT to a String. Either approach results in our object’s data being converted into a single String value that we can pass as a parameter, store in a database or send as the body of an email or Microsoft Message Queue (MSMQ) message. Once the data reaches the other end of its journey we can easily reconstitute our object by converting the String value back into its original form.





Page 5 of 13



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date
Rocket Fuel