I propose that we build a VB client that uses ADO for the ordinary database access and the MSMQ ActiveX objects for the message queuing, plus our own ATL-developed transactional object for the transfer. This is what our VB application’s form looks like:
The top section of the form contains a list of all the Beanie Babies that this client is currently actively looking for. This is constructed by going through all the Beanie Babies in his or her database, and extracting the names of all those with the “wanted” bit set. If we’re about to give up looking for one of them, we click on the Offer button, which adds it to the queue of those available for others to take over the search. If we actually find one of them, we click on the Got button. This clears the “Wanted” bit on the record, and it disappears from the list. If we made a mistake with one of the names, we can delete it altogether by clicking on the Delete button.
The text box in the middle, and the Add button are used to enter names for new Beanie Babies. These immediately become wanted, and are added to our list. There isn’t, incidentally, a mechanism to ensure that the same Beanie Baby is added to several people’s databases at the same time – a small flaw in the system.
The bottom section of the form is used if we want to take over the search for a Beanie Baby from someone else – say, for example, if we’ve just found a really good supplier that has got lots of really rare ones. We select a specific machine's queue to look at by means of the combo box at the bottom, and the list of Beanie Babies that are currently on that queue appears in the list box above. If we select one, and click on the Take button, it moves over to our database; this is the transactional stuff.
So, from the point of view of one node connected to the offered queue, this is where the information is moved from and to:
Here’s an example in practice:
Here, our client (on node dipsy), is already actively looking for Britannia, Doby, Hoot and so on. Our colleague on node tinky-winky, meanwhile, has given up looking for Lefty, Righty and Princess and is offering the search opportunity to others. If we happen to know of a place where we can get hold of a Princess, for instance (and I’m not telling you where our daughter got hers from), we could choose to take Princess off the queue and put it into our database.
OK, what does the code look like?
This is the VB code for the routine that refreshes the “wanted” list:
Private Sub RefreshWanted()
lstWanted.Clear
Dim conn As ADODB.Connection
Set conn = New Connection
conn.Open dbopen
Dim rs As ADOR.Recordset
Set rs = New Recordset
rs.Open "checklist", conn, adOpenForwardOnly, adLockPessimistic, _
adCmdTable
Dim fields As ADODB.fields
Dim field As ADODB.field
Dim name As String
Dim want As Boolean
Do While Not rs.EOF
Set fields = rs.fields
For Each field In fields
If field.name = "description" Then
name = field.Value
ElseIf field.name = "wanted" Then
want = field.Value
End If
Next field
' Only add wanted items to the list
If want Then
lstWanted.AddItem Trim(name)
End If
rs.MoveNext
Loop
Set fields = Nothing
Set rs = Nothing
Set conn = Nothing
End Sub
Notice how ADO makes walking sequentially through a database really very straightforward. Now let’s see some of the message queue handling code. This is the bit that outputs the contents of a queue, when the combo box at the bottom is selected:
Private Sub cmbQueueList_Click()
lstOffered.Clear
Dim info As New MSMQQueueInfo
info.PathName = cmbQueueList.Text
Dim q As MSMQQueue
Set q = info.Open(MSMQ.MQ_PEEK_ACCESS, MSMQ.MQ_DENY_NONE)
Dim message As MSMQMessage
Set message = q.PeekCurrent(, , 100)
Do While Not message Is Nothing
lstOffered.AddItem message.Label
Set message = q.PeekNext(, , 100)
Loop
End Sub
All of which bears a considerable resemblance to the MFC stuff in our earlier e-mail example (except ever so slightly cleaner). Once again, it’s a question of peeking through our queue, picking off all the labels. Incidentally, our messages here have no body — they’re just a label.
Now we get to the interesting bit. This is what happens when we click the Offer button:
Private Sub cmdOffer_Click()
Dim count As Integer
Dim index As Integer
count = lstWanted.ListCount
For index = 0 To count - 1
If (lstWanted.Selected(index)) Then
Dim item As String
item = lstWanted.List(index)
Dim xfer As Transfer
Set xfer = New Transfer
xfer.PutOnQueue item
End If
Next index
RefreshWanted
End Sub
The critical part here is where we instantiate a Transfer
object, and invoke the PutOnQueue()
method. This Transfer
object is running under MTS, so we’re going to be doing some transactional maneuvers. This is where we get to do some ATL work (Ah! Real programming at last!). I won’t show you the rest of the VB stuff here, but if you want it, it’s available for download from www.wrox.com.