Freigeben über


Erkennen und Beheben von Konflikten

Wenn Sie sich mit Ihrem Recordset im unmittelbaren Modus befassen, besteht viel weniger Wahrscheinlichkeit, dass Parallelitätsprobleme auftreten. Wenn Ihre Anwendung dagegen die Batchmodusaktualisierung verwendet, besteht möglicherweise die Möglichkeit, dass ein Benutzer einen Datensatz ändert, bevor änderungen, die von einem anderen Benutzer vorgenommen wurden, der denselben Datensatz bearbeitet hat, gespeichert werden. In einem solchen Fall möchten Sie, dass Ihre Anwendung den Konflikt ordnungsgemäß behandelt. Es kann Ihr Wunsch sein, dass die letzte Person, die ein Update an den Server sendet, "gewinnt". Oder Sie möchten den letzten Benutzer entscheiden lassen, welche Aktualisierung Vorrang haben soll, indem Sie ihm eine Auswahl zwischen den beiden widersprüchlichen Werten zur Verfügung stellen.

Unabhängig vom Fall stellt ADO die UnderlyingValue- und OriginalValue-Eigenschaften des Field-Objekts bereit, um diese Arten von Konflikten zu behandeln. Verwenden Sie diese Eigenschaften in Kombination mit der Resync-Methode und der Filter-Eigenschaft des Recordset.

Bemerkungen

Wenn ADO während einer Batchaktualisierung einen Konflikt findet, wird der Errors-Auflistung eine Warnung hinzugefügt. Daher sollten Sie immer sofort nach dem Aufrufen von BatchUpdate auf Fehler überprüfen, und wenn Sie sie finden, sollten Sie mit dem Testen der Annahme beginnen, dass ein Konflikt aufgetreten ist. Der erste Schritt besteht darin, die Filter-Eigenschaft für das Recordset auf "adFilterConflictingRecords" festzulegen. Dadurch wird die Ansicht auf Ihr 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 durch einen anderen Konflikt ausgelöst wurde.

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

Rufen Sie als Nächstes die Resync-Methode für das Recordset auf, indem Sie das Argument "AffectRecords" auf "adAffectGroup" und das Argument "ResyncValues" auf "adResyncUnderlyingValues" setzen. Die Resync-Methode 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, d. h. nur die widersprüchlichen Datensätze, mit der Datenbank neu synchronisiert werden. Dies kann zu einem erheblichen Leistungsunterschied führen, wenn Sie mit einem großen Recordset umgehen. Durch Festlegen des Arguments "ResyncValues" auf "adResyncUnderlyingValues" beim Aufrufen von Resync stellen Sie sicher, dass die UnderlyingValue-Eigenschaft den (widersprüchlichen) Wert aus der Datenbank enthält, dass die Value-Eigenschaft den vom Benutzer eingegebenen Wert verwaltet und dass die OriginalValue-Eigenschaft den ursprünglichen Wert für das Feld enthält (der Wert, den sie vor dem letzten erfolgreichen UpdateBatch-Aufruf hatte). Anschließend können Sie diese Werte verwenden, um den Konflikt programmgesteuert zu lösen, oder der Benutzer muss den verwendeten Wert auswählen.

Diese Technik wird im folgenden Codebeispiel gezeigt. Das Beispiel erstellt künstlich einen Konflikt, indem ein separates Recordset verwendet wird, 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 Status-Eigenschaft des aktuellen Datensatzes oder eines bestimmten Felds verwenden, um zu bestimmen, welche Art eines Konflikts aufgetreten ist.

Ausführliche Informationen zur Fehlerbehandlung finden Sie unter Fehlerbehandlung.

Siehe auch

Batch-Modus