ACC: How to Use the ReplicationConflictFunction Property

Last reviewed: August 29, 1997
Article ID: Q158930
The information in this article applies to:
  • Microsoft Access versions 7.0, 97
  • Microsoft Access Developer's Toolkit version 7.0
  • Microsoft Office 97 Developer Edition Tools

SUMMARY

Advanced: Requires expert coding, interoperability, and multiuser skills.

This article describes how to use the ReplicationConflictFunction property in a database replica set so that you can create a custom procedure to resolve synchronization conflicts.

MORE INFORMATION

When you use replicated databases in Microsoft Access, you may encounter synchronization errors from time to time. Microsoft Access includes a Conflict Resolver wizard to help you resolve those conflicts when they occur.

However, you may want to create your own procedure to help users resolve synchronization conflicts. Also, the Microsoft Access Developer's Toolkit license agreement does not permit you to distribute wizards with your run- time applications; therefore, you must create your own conflict resolution procedure if your run-time application includes replicated databases.

The ReplicationConflictFunction property enables you to use a custom procedure to resolve conflicts instead of using the Conflict Resolver wizard. The procedure you create to resolve conflicts must be in a replicable module in the Design Master.

Creating a Custom Conflict Resolver

Your custom procedure must be able to process three types of errors:

  • Synchronization conflicts
  • Synchronization errors
  • Design errors

Synchronization Conflicts

Synchronization conflicts occur when one record in a table is updated at two or more different replicas. Even if the changes are made to different fields in the record, the Microsoft Jet database engine treats it as a conflict. The Jet database engine does not attempt to resolve the conflict. Instead, it uses an algorithm to select one version of the record as the official change, and it stores the other version in a conflict table.

Conflict tables are named <tablename>_Conflict, where <tablename> is the table in which the conflict occurred. You can detect conflicts using Visual Basic code by looking for the ConflictTable property of a table. The following portion of a procedure checks for the existence of conflict tables in a replica database:

   Sub ViewSyncConflict()
      Dim Db As DATABASE
      Dim Td As TableDef
      Dim i as Integer
      Set Db = CurrentDb
      ' Step backward through the TableDefs collection so you
      ' do not miss any tables when you delete conflict tables.
      For i = Db.TableDefs.Count - 1 to 0 Step -1
         Set Td = Db.Tabledefs(i)
         If (Td.ConflictTable <> "") Then
            ' Open a recordset based on the conflict table.
            ' Insert code to do conflict resolution.
            ' Delete the conflicting record when you are done.
            ' Delete the conflict table when all its records are deleted.
            ' Set the ConflictTable property to "".
         End If
      Next i
   End Sub

Synchronization Errors

Synchronization errors can come from at least four different sources:

  • A table-level validation rule is applied and other replicas have data that does not satisfy the rule.
  • A duplicate key error occurs because two different replicas entered the same primary key into a table.
  • A referential integrity error occurs because a primary table record is deleted in one replica, and a record is added to a related table in another replica.
  • A record is locked when synchronization occurs.

Synchronization errors are recorded in the MSysErrors table and are replicated to all members of the replica set. Once you have corrected the errors, the Jet database engine automatically removes the error records during a subsequent synchronization.

Open the MSysErrors table to see what errors occurred. The following portion of a procedure displays the synchronization errors in the MSysErrors table:

   Sub ViewSyncError()
      Dim Db As DATABASE
      Dim Rs As Recordset
      Dim MsgString As String
      On Error GoTo ErrorHandler
      Set Db = CurrentDb
      Set Rs = Db.OpenRecordset("MSysErrors", dbOpenSnapshot)
      Rs.MoveLast
      If Rs.RecordCount > 0 Then
         Rs.MoveFirst
         Do Until Rs.EOF
            ' Build the error message string.
            MsgString = "Table ID: " & Rs!TableGUID & vbCr
            MsgString = MsgString & "Record ID: " & Rs!RowGUID & vbCr
            MsgString = MsgString & "Operation: " & Rs!Operation & vbCr
            MsgString = MsgString & "Failed Because: " & Rs!ReasonText
            MsgBox MsgString
            Rs.MoveNext
         Loop
      End If

   ExitProc:
      Exit Sub

   ErrorHandler:
      ' If the MSysErrors table is empty...
      If Err.Number = 3021 Then
         Resume ExitProc
      ' display any other error that occurs.
      Else
         MsgBox Err.Description
         Resume ExitProc
      End If
   End Sub

Design Errors

A design error occurs when a local object exists with the same name as a replicable object in the Design Master. For example, if a user at a replica creates a local form called Form1, and you create a replicable form in the Design Master called Form1, synchronization fails. The design error is recorded in a system table called MSysSchemaProb. The records in MSysSchemaProb are automatically deleted when the conflict is resolved and the design change is successfully synchronized.

The following sample procedure checks for the existence of the MSysSchemaProb table, and displays the design error:

   Sub ViewDesignError()
      Dim Db As DATABASE
      Dim Rs As Recordset
      Dim MsgString As String
      On Error GoTo ErrorHandler
      Set Db = CurrentDb
      Set Rs = Db.OpenRecordset("MSysSchemaProb", dbOpenSnapshot)
      Rs.MoveFirst
      Do Until Rs.EOF
         ' Build the error message string.
         MsgString = "Operation: " & Rs!Command & vbCr
         MsgString = MsgString & "Failed Because: " & Rs!ErrorText
         MsgBox MsgString
         Rs.MoveNext
      Loop

   ExitProc:
      Exit Sub

   ErrorHandler:
         ' If the MSysSchemaProb table does not exist.
         If Err.Number = 3078 Then
            Resume ExitProc
         ' If the MSysSchemaProb table is empty.
         ElseIf Err.Number = 3021 Then
            Resume ExitProc
         ' Display any other error that occurs.
         Else
            MsgBox Err.Description
            Resume ExitProc
         End If
   End Sub

Putting It All Together

Once you have decided how you want to handle each type of synchronization error, create the custom function to use when conflicts occur. The following example combines the sample procedures in each of the earlier sections into a single function:

   Function MyCustomFunction()
      ViewSyncConflict
      ViewSyncError
      ViewDesignError
   End Function

Setting the ReplicationConflictFunction Property

You can set the ReplicationConflictFunction property programmatically or through the user interface. When you set the property programmatically, you may have to add ReplicationConflictFunction to the Properties collection of the database first, and then set its value.

Setting the ReplicationConflictFunction Programmatically

  1. Open the Design Master database for the replica set.

  2. Create a module and type the following procedure:

          Sub SetCustomFunction(FunctionName As String)
             Dim Db As DATABASE, Ctr As Container, Doc As Document
             Dim Prp As Property
             On Error GoTo ErrorHandler
             Set Db = CurrentDb
             Set Ctr = Db.Containers!Databases
             ' Set Document variable pointing to user defined document.
             Set Doc = Ctr.Documents!UserDefined
             ' Set the ReplicationConflictFunction property if it exists.
             Doc.Properties!ReplicationConflictFunction = FunctionName
          Exit Sub
    
          ErrorHandler:
             ' If the property does not exist...
             If Err.Number = 3270 Then
                ' create ReplicationConflictFunction property and set its
                ' value.
                Set Prp = Doc.CreateProperty("ReplicationConflictFunction", _
                    dbText, FunctionName)
                ' Append the new property to the collection.
                Doc.Properties.Append Prp
                ' Resume the main procedure.
                Resume Next
             Else
                ' Display any other error that occurs.
                MsgBox Err.Number & ": " & Err.Description, vbCritical
             End If
          End Sub
    
    

  3. To test this function, type the following line in the Debug window, and then press ENTER.

          SetCustomFunction("MyCustomFunction()")
    

Setting the ReplicationConflictFunction Through the User Interface

  1. Open the Design Master database for the replica set.

  2. On the File menu, click Database Properties.

  3. In the <DatabaseName> Properties dialog box, click the Custom tab.

  4. Set the following properties:

          Name: ReplicationConflictFunction
          Type: Text
          Value: MyCustomFunction()
    

  5. Click OK to close the Properties dialog box.

For more information about using replication in your database, please see the following articles in the Microsoft Knowledge Base for instructions on obtaining the Microsoft Jet Database Replication white paper:

   ARTICLE-ID: Q138828
   TITLE     : ACC95: Microsoft Jet Replication White Paper Available on
               MSL

   ARTICLE-ID: Q164553
   TITLE     : ACC97: Jet 3.5 Replication White Paper Available on MSL
Keywords          : kbprg PgmHowTo
Version           : 7.0 97
Platform          : WINDOWS
Hardware          : x86
Issue type        : kbhowto


================================================================================


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: August 29, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.