我在Excel中编写了一个函数来将记录上传到Access数据库。我在执行recordset.AddNew之后和rs.Update之前模拟了一个错误。我希望数据库不会保存记录,除非.Update执行,但是记录被保存。我的理解是,记录不应该提交到数据库,直到rs.Update执行。这里发生了什么?
下面是我的模块中的一些VBA代码,可以帮助重新创建错误(您还需要设置一个名为“EAS”的Access DB,其中包含一个名为“Statements”的表和一个名为“GroupID”的字段:
模块变量
'Connection
Const PWORD As String = "password"
Dim sSQL As String 'SQL string
Dim cnn As New ADODB.Connection 'ADODB Connection object
Dim rs As New ADODB.Recordset 'ADODB Recordset object
'Paths
Const EAS_DB As String = "J:\yourpath\EAS.accdb"
打开数据库连接
Private Sub openConnect()
'opens the DB connection, let errors occur
Dim cnnString As String
cnnString = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & EAS_DB & ";" & _
"Jet OLEDB:Database Password='" & PWORD & "';"
cnn.Open cnnString
End Sub
关闭数据库连接
Private Sub closeConnect()
'closes recordset and connection cleanly, handle errors
Dim rsFail As Boolean
rsFail = True
On Error GoTo eh:
If Not rs Is Nothing Then
If rs.State = adStateOpen Then
rs.Close
Set rs = Nothing
End If
End If
closeCnn:
rsFail = False
If Not cnn Is Nothing Then
If cnn.State = adStateOpen Then
cnn.Close
Set cnn = Nothing
End If
End If
Exit Sub
eh:
If rsFail Then
GoTo closeCnn:
Else
MsgBox Err.Source & vbNewLine & vbNewLine & Err.Description, , "Error in closeConnect"
End If
End Sub
记录到数据库的函数
Private Function createPendingRecord(ByVal idarray As Variant, ByVal amount As Double) As Boolean
'Attempts to create a new pending record in the database, returns boolean result
Dim data As Variant
Dim flds As Variant
'Get data and field arrays for upload
data(0) = "12345"
flds(0) = "GroupID"
On Error GoTo eh:
openConnect
rs.Open "Statements", cnn, adOpenDynamic, adLockOptimistic
rs.AddNew flds, data
Error 0
rs.Update
createPendingRecord = True
cleanExit:
closeConnect
Exit Function
eh:
MsgBox Err.Source & vbNewLine & vbNewLine & Err.Description, , "Error in createPendingRecord"
Resume cleanExit
End Function
正如你所看到的,我在rs.AddNew
和rs.Update
之间插入了一行Error 0
。这会触发错误处理程序,代码使用closeConnect
退出,而不执行rs.Update
。但是,之后该记录会出现在数据库中。
我的理解是不应该。困惑。请有人能解释一下这是怎么回事吗?
1条答案
按热度按时间5f0d552i1#
你的理解是错误的。这是有意的行为。
查看docs:
AddNew方法的行为取决于对象的更新模式以及是否传递Fieldlist和Values参数。
在立即更新模式下(在这种情况下,一旦调用Update方法,提供程序就将更改写入基础数据源),调用不带参数的AddNew方法会将EditMode属性设置为adEditAdd(EditModeEnum值)。提供程序将在本地缓存任何字段值更改。调用Update方法将新记录发送到数据库,并将EditMode属性重置为adEditNone(EditModeEnum值)。如果传递Fieldlist和Values参数,ADO将立即将新记录发送到数据库(不需要Update调用);EditMode属性值不会更改(adEditNone)。
由于您传递的是字段和值列表,并且没有使用批处理模式,因此新记录会立即写入,后续的
.Update
是不必要的。如果你想取消操作,最直接的方法是使用事务(参见this),这将允许你更好地控制何时将更改写入数据库。
或者,您可以逐个分配字段和值,而不使用
.AddNew
中的字段和值列表,这将适用于此特定操作。