다음을 통해 공유


충돌 검색 및 해결

즉시 모드에서 Recordset을 처리하는 경우 동시성 문제가 발생할 가능성이 훨씬 적습니다. 반면 애플리케이션에서 일괄 처리 모드 업데이트를 사용하는 경우 동일한 레코드를 편집하는 다른 사용자가 변경한 내용이 저장되기 전에 한 사용자가 레코드를 변경할 가능성이 높습니다. 이러한 경우, 애플리케이션이 충돌을 우아하게 처리하도록 하고 싶을 것입니다. 서버에 업데이트를 보낼 마지막 사람이 "승리"하는 것이 당신의 소원일 수 있습니다. 또는 가장 최근 사용자가 충돌하는 두 값 중에서 선택할 수 있도록 하여 우선 순위를 지정해야 하는 업데이트를 결정하도록 할 수 있습니다.

어떤 경우든 ADO는 이러한 유형의 충돌을 처리하기 위해 Field 개체의 UnderlyingValue 및 OriginalValue 속성을 제공합니다. 이러한 속성을 레코드 집합의 Resync 메서드 및 Filter 속성과 함께 사용합니다.

발언

일괄 업데이트 중에 ADO에서 충돌이 발생하면 오류 컬렉션에 경고가 추가됩니다. 따라서 BatchUpdate를 호출한 직후에 항상 오류를 확인해야 하며, 오류가 발견되면 충돌이 발생했음을 가정하여 테스트를 시작해야 합니다. 첫 번째 단계는 레코드 집합의 Filter 속성을 adFilterConflictingRecords와 동일하게 설정하는 것입니다. 이렇게 하면 레코드 집합의 보기가 충돌하는 레코드로만 제한됩니다. 이 단계 이후 RecordCount 속성이 0과 같으면 충돌이 아닌 다른 항목으로 인해 오류가 발생한 것을 알 수 있습니다.

BatchUpdate를 호출할 때 ADO와 공급자는 데이터 원본에 대한 업데이트를 수행하기 위해 SQL 문을 생성합니다. 특정 데이터 원본에는 WHERE 절에서 사용할 수 있는 열 형식에 제한이 있습니다.

다음으로, AffectRecords 인수가 adAffectGroup과 같고 ResyncValues 인수가 adResyncUnderlyingValues와 같게 설정된 Recordset에서 Resync 메서드를 호출합니다. Resync 메서드는 기본 데이터베이스에서 현재 Recordset 개체의 데이터를 업데이트합니다. adAffectGroup을 사용하면 현재 필터 설정으로 표시되는 레코드, 즉 충돌하는 레코드만 데이터베이스와 다시 동기화되도록 합니다. 이렇게 하면 큰 레코드 집합을 처리하는 경우 성능이 크게 달라질 수 있습니다. Resync를 호출할 때 ResyncValues 인수를 adResyncUnderlyingValues로 설정하면 UnderlyingValue 속성에 데이터베이스의 (충돌하는) 값이 포함되고, Value 속성이 사용자가 입력한 값을 유지하며, OriginalValue 속성에 필드의 원래 값(마지막으로 성공한 UpdateBatch 호출 전에 있었던 값)이 포함되는지 확인합니다. 그런 다음 이러한 값을 사용하여 프로그래밍 방식으로 충돌을 해결하거나 사용자가 사용할 값을 선택하도록 요구할 수 있습니다.

이 기술은 다음 코드 예제에 나와 있습니다. 이 예제에서는 UpdateBatch가 호출되기 전에 별도의 Recordset을 사용하여 내부 테이블의 값을 변경하여 인위적으로 충돌을 만듭니다.

'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 속성을 사용하여 어떤 종류의 충돌이 발생했는지 확인할 수 있습니다.

오류 처리에 대한 자세한 내용은 오류 처리참조하세요.

참고 항목

일괄 처리 모드