views:

47

answers:

2

I use the DAO method Execute to delete some records. If this fails this is clear by checking RecordsAffected (it will be 0). But is it possible to get the error message (for instance, to log or to show to the user)? I've try to delete the records by hand in the Table grid I get a clear dialog message, e.g. "The record cannot be deleted or changed because tabel x includes related records".

+1  A: 

It should be possible to use DBEngine errors: http://msdn.microsoft.com/en-us/library/bb177491(office.12).aspx

Remou
+1  A: 

Include the dbFailOnError option with the Execute method to capture your DELETE errors. Without dbFailOnError, your DELETE can fail silently.

Relying on RecordsAffected to indicate a DELETE failure can be misleading. For example if your DELETE includes "WHERE Sample=5", and there is no row with a Sample value of 5, RecordsAffected will be 0. That is not an error to the database engine.

In the following sample, the DELETE fails because there is a relationship, with referential integrity enforced, between tblParent and tblChild. So the message box says "The record cannot be deleted or changed because table 'tblChild' includes related records".

Public Sub DeleteFailure()
    Dim strSql As String
    Dim strMsg As String
    Dim db As DAO.Database

On Error GoTo ErrorHandler

    strSql = "DELETE FROM tblParent WHERE id = 1;"
    Set db = CurrentDb
    db.Execute strSql, dbFailOnError

ExitHere:
    On Error GoTo 0
    Debug.Print "RecordsAffected: " & db.RecordsAffected
    Set db = Nothing
    Exit Sub

ErrorHandler:
    strMsg = "Error " & Err.Number & " (" & Err.Description _
        & ") in procedure DeleteFailure"
    MsgBox strMsg
    GoTo ExitHere
End Sub

Update: Here is a revised ErrorHandler to accommodate multiple errors triggered by a DAO operation.

ErrorHandler:
    Dim errLoop As Error
    Debug.Print "Errors.Count: " & Errors.Count
    For Each errLoop In Errors
        With errLoop
            strMsg = "Error " & Err.Number & " (" & _
                Err.Description & _
                ") in procedure DeleteFailure"
        End With
        MsgBox strMsg
    Next
    Set errLoop = Nothing
    GoTo ExitHere
HansUp
The error collection for the DBEngine can be somewhat complicated, as noted in the link I posted. You may have to loop over the collection to get a full message.
Remou
I was a bit confused by this: "If part of a statement executed with dbFailOnError failed, the entire statement would be rolled back. To improve performance, these implicit transactions were removed starting with version 3.5. If you are updating older DAO code, be sure to consider using explicit transactions around Execute statements." (http://msdn.microsoft.com/en-us/library/bb243015%28v=office.12%29.aspx) But it is about transactions. I still can use dbFailOnError, but do the transaction myself (BeginTrans/Commit)
waanders
HansUp> Thanks. Sure RecordsAffected returns 0 if no records need to be removed. For that I first check if records need to be removed, otherwise I don't call the Execute method
waanders
Remou> Err.Description in the example of HansUp works fine for me, I get the same message as with the Table datagrid delete action
waanders
@waanders If you capture an error with Execute and dbFailOnError while a transaction is in progress, you can Rollback the transaction.
HansUp
@Remou I overlooked possibility of multiple errors; revised the answer in response.
HansUp
I'm not sure that the Jet/ACE database engine ever returns an error collection. I know that ODBC databases often do, but I really don't think it's the case with Jet/ACE itself. Of course, the collection code works with a collection with a .Count of 1, so it's good protection for upsizing, but I don't believe it's essential with Jet/ACE.
David-W-Fenton