Dim objRs1 As New ADODB.Recordset Dim objRs2 As New ADODB.Recordset Dim strSQL As String Dim strMsg As String
strSQL = "SELECT * FROM Shippers WHERE ShipperID = 2"
'Open Rs and change a value 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.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
'Clean up objRs1.Close Set objRs1 = Nothing Exit Sub
ErrHandler:
If Not objRs1 Is Nothing Then If objRs1.State = adStateOpen Then objRs1.Close Set objRs1 = Nothing End If
If Not objRs2 Is Nothing Then If objRs2.State = adStateOpen Then objRs2.Close Set objRs2 = Nothing End If
If Err <> 0 Then MsgBox Err.Source & "-->" & Err.Description, , "Error" End If
'EndConflicts 可以使用当前 Record 的或特定 Field 的 Status 属性来确定已发生的冲突种类。
另外和Access一样,是免费的
再Office,SQL Server的安装包里面都有安装程序
存储过程和触发器之类的用到现学则可以,用不到的话跟ACCESS的区别也不大,有一些SQL语句里面的函数有些差别而已!!
也可以是用乐锁定类型来做。检测和解决冲突:
如果在立即模式中处理 Recordset,则很少出现并发问题。另一方面,如果应用程序使用批模式更新,则在保存由一个正在编辑记录的用户所作的更改之前,编辑同一个记录的另一个用户比较有可能会更改记录。在这种情况下,需要应用程序准确处理冲突。您可能希望第一个人将更新发送给服务器成功,或者可能希望通过向最靠近的用户提供两个冲突值作为选择项,让该用户来决定哪个更新应当优先。
无论哪种情况,都可以使用 ADO 提供的 Field 对象的 UnderlyingValue 和 OriginalValue 属性来处理这些类型的冲突。将这些属性与 Recordset 的 Resync 方法和 Filter 属性配合使用。
检测错误:
在批更新期间 ADO 遇到冲突时,将在 Errors 集合中放入警告。因此,调用 BatchUpdate 之后,一定要立即检查是否有错误,如果找到了错误,则应当假设已遇到冲突并开始进行测试。第一步要将 Recordset 的 Filter 属性设置为等于 adFilterConflictingRecords,该设置将使视图 Recordset 限制为只显示哪些发生冲突的记录。如果这一步之后 RecordCount 属性等于零,就说明错误是由冲突以外的其他原因引起的。调用 BatchUpdate 时,ADO 和提供者将生成对数据源执行更新的 SQL 语句。某些数据源对哪些类型的列可以用在 WHERE 子句中存在限制。下一步,调用 Recordset 的 Resync 方法,并且将 AffectRecords 参数设置为等于 adAffectGroup,将 ResyncValues 参数设置为等于 adResyncUnderlyingValues。Resync 方法将用来自基本数据库中的数据刷新在当前 Recordset 对象中的数据。通过使用 adAffectGroup,可以确保只有使用当前筛选设置的情况下可见的记录(即只有冲突记录)会与数据库重新同步。如果处理的是大型 Recordset,该操作会对性能有较大影响。通过在调用 Resync 时将 ResyncValues 参数设置为 adResyncUnderlyingValues,可以确保 UnderlyingValue 属性将包含数据库中的(冲突)值,并确保 Value 属性仍然是由用户输入的值,还会确保 OriginalValue 属性将持有字段的原始值(即在上一次成功进行 UpdateBatch 调用之前该字段所拥有的值)。然后,可以使用这些值通过编程方式解决冲突,或要求用户选择将要使用的值。
示例程序:
'BeginConflicts
On Error GoTo ErrHandler:
Dim objRs1 As New ADODB.Recordset
Dim objRs2 As New ADODB.Recordset
Dim strSQL As String
Dim strMsg As String
strSQL = "SELECT * FROM Shippers WHERE ShipperID = 2"
'Open Rs and change a value
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
'Clean up
objRs1.Close
Set objRs1 = Nothing
Exit Sub
ErrHandler:
If Not objRs1 Is Nothing Then
If objRs1.State = adStateOpen Then objRs1.Close
Set objRs1 = Nothing
End If
If Not objRs2 Is Nothing Then
If objRs2.State = adStateOpen Then objRs2.Close
Set objRs2 = Nothing
End If
If Err <> 0 Then
MsgBox Err.Source & "-->" & Err.Description, , "Error"
End If
'EndConflicts
可以使用当前 Record 的或特定 Field 的 Status 属性来确定已发生的冲突种类。