Freigeben über


Erkennen und Lösen von Konflikten

Wenn Sie sich im unmittelbaren Modus mit Ihrem Recordset befassen, besteht viel weniger Chance, dass Parallelitätsprobleme auftreten. Wenn Ihre Anwendung jedoch im Batch-Modus aktualisiert wird, besteht eine gute Chance, dass ein Benutzer einen Datensatz ändert, bevor die Änderungen eines anderen Benutzers, der denselben Datensatz bearbeitet, gespeichert werden. In diesem Fall möchten Sie, dass Ihre Anwendung den Konflikt ordnungsgemäß behandelt. Sie möchten vielleicht, dass die Person, die als letzte eine Aktualisierung an den Server sendet, „gewinnt“. Oder Sie möchten den letzten Benutzer entscheiden lassen, welche Aktualisierung Vorrang haben soll, indem Sie ihm die Wahl zwischen den beiden sich widersprechenden Werten lassen.

Wie auch immer, ADO bietet die Eigenschaften UnderlyingValue und OriginalValue des Field-Objekts, um diese Arten von Konflikten zu behandeln. Verwenden Sie diese Eigenschaften in Kombination mit der Methode Resync und der Eigenschaft Filter des Recordsets.

Bemerkungen

Wenn ADO während eines Batchupdates einen Konflikt findet, wird der Errors-Auflistung eine Warnung hinzugefügt. Daher sollten Sie immer sofort nach dem Aufrufen von BatchUpdate nach Fehlern suchen, und wenn Sie sie finden, beginnen Sie mit dem Testen der Annahme, dass ein Konflikt aufgetreten ist. Der erste Schritt besteht darin, die Filter-Eigenschaft für das Recordset gleich "adFilterConflictingRecords" festzulegen. Dadurch wird die Ansicht auf Ihrem Recordset auf nur die Datensätze beschränkt, die in Konflikt stehen. Wenn die RecordCount-Eigenschaft nach diesem Schritt gleich Null ist, wissen Sie, dass der Fehler von einem anderen Als einem Konflikt ausgelöst wurde.

Wenn Sie BatchUpdate aufrufen, generieren ADO und der Anbieter SQL-Anweisungen, um Updates für die Datenquelle auszuführen. Beachten Sie, dass bestimmte Datenquellen Einschränkungen haben, auf welche Spaltentypen in einer WHERE-Klausel verwendet werden können.

Rufen Sie als Nächstes die Resync-Methode im Recordset auf, wobei das Argument „AffectRecords“ gleich „adAffectGroup“ und das Argument „ResyncValues“ auf „adResyncUnderlyingValues“ festgelegt ist. Die Methode Resync aktualisiert die Daten im aktuellen Recordset-Objekt aus der zugrunde liegenden Datenbank. Mithilfe von adAffectGroup stellen Sie sicher, dass nur die Datensätze, die mit der aktuellen Filtereinstellung sichtbar sind, also nur die konfliktierenden Datensätze, mit der Datenbank neu synchronisiert werden. Dies könnte einen erheblichen Leistungsunterschied machen, wenn Sie mit einem großen Recordset umgehen. Indem Sie das Argument ResyncValues beim Aufruf von Resync auf adResyncUnderlyingValues setzen, stellen Sie sicher, dass die Eigenschaft UnderlyingValue den (widersprüchlichen) Wert aus der Datenbank enthält, dass die Eigenschaft Value den vom Benutzer eingegebenen Wert beibehält und dass die Eigenschaft OriginalValue den ursprünglichen Wert für das Feld enthält (den Wert, den es vor dem letzten erfolgreichen UpdateBatch-Aufruf hatte). Anschließend können Sie diese Werte verwenden, um den Konflikt programmgesteuert zu beheben, oder der Benutzer muss den verwendeten Wert auswählen.

Diese Technik wird in dem folgenden Codebeispiel gezeigt. Das Beispiel schafft künstlich einen Konflikt, indem es ein separates Recordset verwendet, um einen Wert in der zugrunde liegenden Tabelle zu ändern, bevor UpdateBatch aufgerufen wird.

'BeginConflicts  
    strConn = "Provider=SQLOLEDB;Initial Catalog=Northwind;" & _  
              "Data Source=MySQLServer;Integrated Security=SSPI;"  
  
    strSQL = "SELECT * FROM Shippers WHERE ShipperID = 2"  
  
    'Open Rs and change a value  
    Set objRs1 = New ADODB.Recordset  
    Set objRs2 = New ADODB.Recordset  
    objRs1.CursorLocation = adUseClient  
    objRs1.Open strSQL, strConn, adOpenStatic, adLockBatchOptimistic, adCmdText  
    objRs1("Phone") = "(111) 555-1111"  
  
    'Introduce a conflict at the db...  
    objRs2.Open strSQL, strConn, adOpenKeyset, adLockOptimistic, adCmdText  
    objRs2("Phone") = "(999) 555-9999"  
    objRs2.Update  
    objRs2.Close  
    Set objRs2 = Nothing  
  
    On Error Resume Next  
    objRs1.UpdateBatch  
  
    If objRs1.ActiveConnection.Errors.Count <> 0 Then  
        Dim intConflicts As Integer  
  
        intConflicts = 0  
  
        objRs1.Filter = adFilterConflictingRecords  
  
        intConflicts = objRs1.RecordCount  
  
        'Resync so we can see the UnderlyingValue and offer user a choice.  
        'This sample only displays all three values and resets to original.  
        objRs1.Resync adAffectGroup, adResyncUnderlyingValues  
  
        If intConflicts > 0 Then  
            strMsg = "A conflict occurred with updates for " & intConflicts & _  
                     " record(s)." & vbCrLf & "The values will be restored" & _  
                     " to their original values." & vbCrLf & vbCrLf  
  
            objRs1.MoveFirst  
            While Not objRs1.EOF  
              strMsg = strMsg & "SHIPPER = " & objRs1("CompanyName") & vbCrLf  
              strMsg = strMsg & "Value = " & objRs1("Phone").Value & vbCrLf  
              strMsg = strMsg & "UnderlyingValue = " & _  
                                 objRs1("Phone").UnderlyingValue & vbCrLf  
              strMsg = strMsg & "OriginalValue = " & _  
                                 objRs1("Phone").OriginalValue & vbCrLf  
              strMsg = strMsg & vbCrLf & "Original value has been restored."  
  
              MsgBox strMsg, vbOKOnly, _  
                    "Conflict " & objRs1.AbsolutePosition & _  
                    " of " & intConflicts  
  
              objRs1("Phone").Value = objRs1("Phone").OriginalValue  
              objRs1.MoveNext  
            Wend  
  
            objRs1.UpdateBatch adAffectGroup  
        Else  
            'Other error occurred. Minimal handling in this example.  
             strMsg = "Errors occurred during the update. " & _  
                        objRs1.ActiveConnection.Errors(0).Number & " " & _  
                        objRs1.ActiveConnection.Errors(0).Description  
        End If  
  
        On Error GoTo 0  
    End If  
  
    objRs1.MoveFirst  
    objRs1.Close  
    Set objRs1 = Nothing  
'EndConflicts  

Sie können die Eigenschaft Status des aktuellen Datensatzes oder eines bestimmten Feldes verwenden, um festzustellen, welche Art von Konflikt aufgetreten ist.

Ausführliche Informationen zur Fehlerbehandlung finden Sie unter Fehlerbehandlung.

Weitere Informationen

Batchmodus