共用方式為


偵測和解決衝突

如果您在立即模式中處理 Recordset,則發生並行問題的機會要少得多。 另一方面,如果您的應用程式使用批次模式更新,很可能當一位使用者在編輯記錄時,另一位使用者已經對相同的記錄進行變更,而後者的變更尚未被儲存。 在這種情況下,您會想要讓應用程式正常處理衝突。 您可能希望最後一個人傳送更新給伺服器「獲勝」。或者,您可能想要讓最近的用戶決定哪一個更新應該優先,方法是提供他兩個衝突值之間的選擇。

無論情況如何,ADO 都會提供 Field 物件的 UnderlyingValue 和 OriginalValue 屬性來處理這些衝突類型。 將這些屬性與 Recordset 的 Resync 方法和 Filter 屬性搭配使用。

備註

當 ADO 在批次更新期間發生衝突時,警告將會新增至 Errors 集合。 因此,您應該一律在呼叫 BatchUpdate 之後立即檢查錯誤,如果您發現錯誤,請開始測試您遇到衝突的假設。 第一個步驟是在 Recordset 上設定等於 adFilterConflictingRecords 的 Filter 屬性。 這會將 Recordset 上的檢視限制為只有發生衝突的記錄。 如果在這個步驟之後,RecordCount 屬性等於零,您就知道錯誤是由衝突以外的其他因素發生。

當您呼叫 BatchUpdate 時,ADO 和提供者會產生 SQL 語句,以對數據源執行更新。 請記住,某些數據源在 WHERE 子句中可以使用哪些數據行類型有限制。

接下來,呼叫 Recordset 上的 Resync 方法,並將 AffectRecords 自變數設定為等於 adAffectGroup,而 ResyncValues 自變數設定等於 adResyncUnderlyingValues。 Resync 方法會從基礎資料庫更新目前 Recordset 對象中的數據。 藉由使用 adAffectGroup,您可確保只有在目前的篩選設定下可見的記錄,也就是只有衝突記錄會與資料庫重新同步。 如果您正在處理大型 Recordset,這可能會造成顯著的效能差異。 藉由在呼叫 Resync 時將 ResyncValues 自變數設定為 adResyncUnderlyingValues,您可以確定 UnderlyingValue 屬性會包含資料庫中的 (衝突) 值、Value 屬性會維持使用者輸入的值,而且 OriginalValue 屬性會保留字段的原始值(上次成功呼叫 UpdateBatch 呼叫之前的值)。 然後,您可以使用這些值,以程式設計方式解決衝突,或要求用戶選取將使用的值。

下列程式代碼範例顯示這項技術。 此範例會使用個別的 Recordset 在呼叫 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  

您可以使用目前 Record 或特定 Field 的 Status 屬性來判斷發生何種衝突。

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

另請參閱

批次模式