Previous | Index | Next 

[PRB] DAO and RDO Data control may not update bound controls when record position changes

The DAO Data control exposes the Recordset property, which returns a reference to the inner DAO.Recordset object. Similarly, the MSRDC control exposes the Resultset property, which returns a reference to the inner RDO.rdoResultset object. VB6 applications typically use these properties to programmatically move the record pointer or perform other actions on the data, as in this code:

    Me.Data1.Recordset.Update
    Me.Data1.Recordset.MoveNext
    Me.Data1.Recordset.Filter = ""
    Me.Data1.Recordset.AddNew

The VB6Data and VB6RemoteData controls aren’t wrappers on the VB6 ActiveX controls; instead, they simulate all their properties and behaviors of the original VB6 controls, internally using a DAO.Recordset object or an RDO.rdoResultset objects, respectively, to read and write data stored in the database.

Here’s the problem: the DAO.Recordset and RDO.rdoResultset objects don’t fire any event when the current record position changes or some other relevant action is performed. The lack of this event prevents the VB6Data and VB6RemoteData controls from the opportunity to update all bound controls when the application move the current record position by invoking a method exposed by the DAO.Recordset or RDO.rdoResultset object.

VB Migration Partner works around this issue by automatically transforming members of the Recordset (or Resultset) object into "surrogate" members of the VB6Data (or VB6RemoteData) control itself. All the surrogate members of the data control start with "Recordset_" string or "Resultset_" string. For example, the code above is translated to VB.NET as follows:

    Me.Data1.Recordset_Update()
    Me.Data1.Recordset_MoveNext()
    Me.Data1.Recordset_Filter = ""
    Me.Data1.Recordset_AddNew()

where the property or method exposed by the control takes care of keeping all bound controls in sync with the current record.

VB Migration Partner behaves correctly only if it can determine that the control being accessed is a DAO or RDO Data control. If the original code is accessing the Data control in late-bound mode, no transformation can be performed, as in this VB6 code:

    Sub MoveToFirstRecord(ByVal ctrl As Control) 
        ' this method is meant to work with DAO, RDO, and ADO Data controls
        ctrl.Recordset.MoveNext
    End Sub

If the data control is accessed via late binding, you can use an AssumeType pragma to let VB Migration Partner that this is a DAO or RDO Data control. The following fix to the original VB6 code adopts this approach:

    Sub MoveToFirstRecord(ByVal ctrl As Control) 
        '## ctrl.AssumeType VB.Data
        ctrl.Recordset.MoveNext
    End Sub

and causes the correct VB.NET to be generated:

    Sub MoveToFirstRecord(ByVal ctrl As Control) 
        ctrl.Recordset_MoveNext()
    End Sub

Even this workaround fails if you are accessing the DAO.Recordset or the RDO.Resultset object directly, without using the “dot” syntax, as in this VB6 code:

    Dim rs As Recordset
    Set rs = Me.Data1.Recorset
    rs.MoveNext

VB Migration Partner isn’t able to detect that the rs variable points to the Recordset object returned by the Me.Data1.Recordset property and therefore fails to transform the code into a member of the data control.

You can solve this issue by using a ReplaceStatement pragma that manually inserts the call to the proper surrogate method. Alternatively, if there are many occurrences of this kind of code, you can use a PostProcess pragma to perform the transformation automatically. For example, if rs corresponds to the Recordset exposed by the Data1 control, you can transform the AddNew, Update, and all the Move*** methods of the recorset into the corresponding methods of the Data control by means of the following pragma:

    '## PostProcess "rs\.(?<method>Move.*|AddNew|Update)\b", "Data1.Recordset_${method}"

are converted to VB.NET as:

    Data1.UpdateRecord()
    MSRDC1.UpdateRow()
    MSRDC1.UpdateRow(): MSRDC1.Resultset.BatchUpdate

Keep in mind, however, that no additional transformation can be performed if you access the Recordset or rdoResultset object directly. In that case, you should use a ReplaceStatement pragma to do the transformation yourself.

 

Previous | Index | Next