XML

Updating the Data Source

Currently, the data we have been working with has been saved only to a local file. This data will still have to be saved to the original data source (the Northwind Traders database, in this case). To save the updated data, add another command button to the form called cmdSaveUpdate with a caption Save Update and add the following code to the click event handler of the command button cmdSaveUpdate:

  Private Sub cmdSaveUpdate_Click()
  Dim objNWRecordset As ADODB.Recordset
  Dim objNWConnection As ADODB.Connection
  Dim objXMLRecordset As ADODB.Recordset
  Dim lngFieldCounter As Long
  Set objNWRecordset = New ADODB.Recordset
  Set objXMLRecordset = New ADODB.Recordset
  Set objNWConnection = New ADODB.Connection
  objNWConnection.CursorLocation = adUseServer
  'You will need to replace IES-FUJI with the appropriate data
  'source in the following statement.
  objNWConnection.Open _
     "Provider=SQLOLEDB.1;Integrated Security=SSPI;" & _
     "Persist Security Info=False;" & _
     "User ID=sa;Initial Catalog=Northwind;Data Source=IES-FUJI"
  objNWRecordset.CursorLocation = adUseServer
  objNWRecordset.CursorType = adOpenDynamic
  objNWRecordset.LockType = adLockPessimistic
  Set objNWRecordset.ActiveConnection = objNWConnection
  objXMLRecordset.Open "C:\ProductsUpdate.XML", Options:=adCmdFile
  objXMLRecordset.Filter = adFilterPendingRecords
  Do Until objXMLRecordset.EOF
     If objXMLRecordset.EditMode <> adEditAdd Then
        objNWRecordset.Open _
           "Select * From Products Where ProductID=" _
           & objXMLRecordset.Fields.Item("ProductID").OriginalValue
        If objXMLRecordset.EditMode = adEditDelete Then
           'Delete
           objNWRecordset.Delete
        Else
           'Edit
        For lngFieldCounter = 0 To objXMLRecordset.Fields.Count-1
              'Can Not Change Primary Key
           If UCase(objXMLRecordset.Fields.Item( _
              lngFieldCounter).Name) _
              <> "PRODUCTID" Then
              objNWRecordset.Fields.Item(lngFieldCounter).Value = _
                 objXMLRecordset.Fields.Item(lngFieldCounter).Value
           End If
        Next
        End If
     Else
        objNWRecordset.Open _
           "Select * From Products Where ProductID=" & 0
        objNWRecordset.AddNew
          'Add New
        For lngFieldCounter = 0 To objXMLRecordset.Fields.Count - 1
           'Auto Increment field for productID
           If UCase(objXMLRecordset.Fields.Item( _
              lngFieldCounter).Name) _
              <> "PRODUCTID" Then
              objNWRecordset.Fields.Item(lngFieldCounter).Value = _
                 objXMLRecordset.Fields.Item(lngFieldCounter).Value
           End If
        Next
     End If
     objNWRecordset.Update
     objNWRecordset.Close
     objXMLRecordset.MoveNext
     Loop
  End Sub

Once again, we create a Connection object called objNWConnection to connect to the Northwind Traders database, and a Recordset object called objNWRecordset to hold the data from the ProductsUpdate.xml file. You will need to configure the data source and change the connection string again, just like in the previous example. ObjNWRecordset is used to get a reference to the record that is being updated using a SELECT statement with a WHERE clause.

The second Recordset object called objXMLRecordset is used to retrieve the XML data, which contains the data that has been added, edited, or deleted. You can also get the XML data from an ADO data stream, which we'll cover in the section "Working With Streams" later in this chapter.

Once we have obtained the XML data stored in the objXMLRecordset recordset, we apply a filter so that the only visible records are the ones that have had changes done to them or are new records. We then move through each record in objXMLRecordset that is new or has been changed and retrieve that record from the database using objNWRecordset.

Once we have only the records that are about to be changed, we can perform the correct operations: AddNew, Delete, and Edit. We begin by checking the EditMode property of objXMLRecordset to find out which operation was being done on this record, and then perform the operation accordingly.

If you have worked with disconnected ADO recordsets before, you might have expected that we would use the UpdateBatch method of the ADO recordset. Unfortunately, the disconnected ADO recordset created using XML has no reference to the original table that was used to get the data. Thus, even though you can create an ADO connection to the correct database and set the recordset's ActiveConnection property to this connection, there is simply no way of connecting the recordset to the right table. Because the recordset cannot be connected to the correct table, the UpdateBatch method cannot work. As you can see from the above example, we have created two Recordset objects: ObjXMLRecordset and objNWRecordset.

NOTE
In order to keep the code simple, the example we have been working with does not include error handling. Remember that all production code should have error handlers. In this example, you would need to check the record that is about to be changed to make sure it actually exists in the database and has not been changed by someone else. You can check the status of the data by using the PreviousValue property of the Recordset object for each field. The PreviousValue property will give the value of the field before it was changed. We have used query strings containing table and field names in the code; however, in production code, we would use constants so that only the value of the constant would need to be changed if the table or field names changed.