共用方式為


偵測並解決衝突

如果您是以立即模式處理資料錄集,則發生並行問題的可能性較低。 另一方面,如果您的應用程式使用批次模式進行更新,則很可能會有一個使用者在另一個編輯相同記錄的使用者儲存其所做的變更之前變更記錄。 在這種情況下,您會希望應用程式能夠正常處理衝突。 您可能想要讓最後將更新傳送至伺服器的人「勝出」。或者,您可能會想要為最新的使用者提供兩個衝突值之間的選擇,讓他決定哪些更新應優先。

無論是哪種情況,ADO 都會提供 Field 物件的 UnderlyingValue 和 OriginalValue 屬性來處理這些類型的衝突。 請將這些屬性與資料錄集的 Resync 方法和 Filter 屬性搭配使用。

備註

ADO 在批次更新期間遇到衝突時,會將警告新增至 Errors 集合。 因此,您應一律在呼叫 BatchUpdate 之後立即檢查錯誤,如果發現錯誤,請開始測試您遇到衝突的假設。 第一個步驟是將資料錄集上的 Filter 屬性設定為 adFilterConflictingRecords。 這會將資料錄集上的檢視限定於發生衝突的記錄。 如果 RecordCount 屬性經此步驟後等於零,則可得知錯誤並非衝突所引起的。

當您呼叫 BatchUpdate 時,ADO 和提供者會產生 SQL 陳述式,以對資料來源執行更新。 請記住,某些資料來源具有哪些類型的資料行可在 WHERE 子句中使用的限制。

接著,將 AffectRecords 引數設定為 adAffectGroup,並將 ResyncValues 引數設定為 adResyncUnderlyingValues,在資料錄集上呼叫 Resync 方法。 Resync 方法會從基礎資料庫更新目前 Recordset 物件中的資料。 使用 adAffectGroup,可以確保只有透過目前的篩選設定可見的記錄 (即只有發生衝突的記錄) 會與資料庫重新同步處理。 如果您處理的是大型資料錄集,這可能會造成顯著的效能差異。 在呼叫 Resync 時將 ResyncValues 引數設定為 adResyncUnderlyingValues,可確保 UnderlyingValue 屬性將包含資料庫中的 (衝突) 值,Value 屬性將保有使用者輸入的值,且 OriginalValue 屬性會保留欄位的原始值 (上次成功呼叫 UpdateBatch 呼叫之前的值)。 您隨後可以使用這些值以程式設計方式解決衝突,或要求使用者選取將使用的值。

下列程式碼範例中顯示了這項技巧。 此範例使用個別的資料錄集,在呼叫 UpdateBatch 之前變更基礎資料表中的值,而刻意產生衝突。

'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  

您可以使用目前的記錄或特定欄位的 Status 屬性,判斷發生的是何種衝突。

如需錯誤處理的詳細資訊,請參閱錯誤處理

另請參閱

批次模式