2016-03-20 8 views
1

Ich habe über Fehlerbehandlung gefragt. Wenn während der Codeausführung ein Fehler auftritt und ich ein Recordset geöffnet habe, sollte ich es schließen? Das Versuchen einer recordset.close-Operation kann einen Fehler auslösen, und da ich mich in einem Codeabschnitt für die Fehlerbehandlung befinde, handelt es sich um einen unbehandelten Fehler.Zugriff schließen Recordset in Fehlerbehandlung

Wenn ich den Code zurückschicke, um mit einem anderen Label fortzufahren, kann es zur Endlosschleife werden. Wenn nun ein Boolescher Wert hinzugefügt wird, um zu prüfen, ob der Fehler zum ersten Mal aufgetreten ist, würde das funktionieren, aber brauche ich wirklich diesen ganzen Aufwand? Bleibt die Verbindung offen, wenn der Code terminiert und ich schließe ihn nicht? Wird es später Probleme geben?

Dim rs As DAO.Recordset 

Set rs = CurrentDB.OpenRecordset("SELECT * FROM tblSetting") 
On Error GoTo handler 

    'do things 

rs.Close 
Set rs = Nothing 

Exit Sub 

handler: 
rs.Close 
'Set rs = Nothing '-this one is not necessary, as terminating the sub should clear up all references to it, hence Garbage Collector can pick it up 
End Sub 

Das würde funktionieren, aber ... wirklich?

... 
Termination: 
    rs.Close 
    Set rs = Nothing 
Exit Sub 

handler: 
if ErrorHappened=True then 
    msgbox "fatal error" 
    exit sub 
else 
    ErrorHappened=True 
    resume termination 
End If 

Vielen Dank!

Antwort

2

Ja, es ist eine gute Methode, aktuell geöffnete Recordsets und Verbindungen zu schließen. Es gibt viele Gründe, siehe: Pooling in the Microsoft Data Access Components. Dieser Artikel ist ziemlich alt, aber die Hauptsache ist, gehalten ...

Ich würde Ihr Code auf diese Weise verbessern:

Exit_Subroutine: 
    On Error Resume Next 'ignore errors to be able to execute each line 
    If Not rst is Nothing Then rst.Close: Set rst = Nothing 
    'do the same for the connection object! 
    Exit Sub 

ErrorHandler: 
    MsgBox Err.Description, vbCritical, "Error" & Err.Number 
    Resume Exit_Subroutine 

Sie müssen sicher sein, dass rst Objekt ist nicht nichts, bevor Sie attampt zu Schließe es.

+0

Nun, der harte Weg ist es dann ... Danke! – vacip

+0

Ich würde es immer noch nicht direkt in den Fehler-Handler setzen ... Oder nichts anderes kann einen Fehler beim Schließen eines Recordsets verursachen, abgesehen davon, dass es nicht gesetzt ist? – vacip

+1

Danke. Tut mir leid, ich war etwas beschäftigt. Ich fügte dem Code zusätzliche Zeilen hinzu und verbesserte den Fehlerhandler. Dies ist der Code, den ich oft benutze - für allgemeine Zwecke. Natürlich können Sie es ändern, um bestimmte Fehlernummer zu fangen und zu behandeln. –

1

VBA verfügt über automatische Speicherbereinigung. Wenn im VBA-Compiler nichts schief geht, werden alle Objekte freigegeben, wenn sie den Gültigkeitsbereich verlassen. In Ihrem Beispiel:

Dim rs As DAO.Recordset 

'do things 
Exit Sub 

'do things 
End Sub 

... rs wird am End-Sub freigegeben und automatisch geschlossen. (FWIW, sehen Sie dies, indem Sie den kompilierten Code untersuchen).

Klassisches ASP hatte keinen solchen Bereich, und Objekte gingen nie aus dem Geltungsbereich und Re-Cord-Sets wurden nie automatisch freigegeben. Aus diesem Grund zeigen ALLE Microsoft VBA-Beispiele EXPLICIT CLOSE und RELEASE. Das muss für ASP Classic so gemacht werden.

Es gibt zwei weitere Gründe dafür explizit schließen und freigeben:

1) C/C++ Programmierer haben keine automatische Speicherverwaltung. Sie waren voller Entsetzen und Abscheu vor der Idee, Objekte offen zu lassen. Dies ist ein Codierungsstil.

2) Einige Leute behaupten, dass in einem nicht identifizierten Fehlerzustand irgendwie lokale Objekte ohne verbleibende Referenzen nicht automatisch korrekt geschlossen werden. Das habe ich noch nie gesehen. Das habe ich noch nie gesehen. Ich habe nie von einem konkreten Beispiel gelesen. Aber hey, einige Leute behaupten das. Vielleicht ist es wahr.