webForumDet fria alternativet

Bekymmer att stänga ett stängt recordset

.NET

15 svar · 315 visningar · startad av Engine^

Medlem sedan dec. 20003 887 inlägg
Frågan#1

Jag har ett litet bekymmer med en sqlexekveringsfunktion, som ser ut så här

Public Function ExecuteSQL(Optional ByRef rsObject As Recordset) As Long
On Error Goto fn_Err
  Dim objConn As New ADODB.Connection
  
  Set objConn = [i]connection...[/i]
  Set rsObject = New ADODB.Recordset

  If InStr(strSQL, "DELETE") Or InStr(strSQL, "INSERT INTO") Then
    objConn.Execute strSQL, lngRecordsAffected, adExecuteNoRecords
    
    ExecuteSQL = lngRecordsAffected
  ElseIf InStr(strSQL, "SELECT") Then
    rsObject.Open strSQL, objConn, adOpenForwardOnly, adLockReadOnly

    ExecuteSQL = rsObject.RecordCount
  Else
    MsgBox "Ofärdig SQL-funktion..."
  End If

fn_Exit:
    [b]rsObject.Close: Set rsObject = Nothing[/b] <- skapar bekymmer...
    objConn.Close: Set objConn = Nothing
    Exit Function

fn_Err:
    g_intErrNum = Err.Number
    g_strErrDesc = Err.Description
    g_strErrorMsg = FormatSQL((strSQL))
    g_strFunctionName = "ExecuteSQL"
    g_strSourceName = "modGlobalaFunktioner"
    
    Call g_ErrorHandler
    Resume fn_Exit
End Function

Givetvis går det inte att stänga ett recordset som inte är öppet, men hur kontrollerar jag om det är öppet eller inte?

Är det, förresten, bra eller dåligt att hantera sql på detta sätt?

edit
Ops! Det här meddelandet skulle ha blivit postat i VB-forumet.

Medlem sedan juni 200032 967 inlägg
#2

Jag hade nog lagt till en kontrollvariabel, i brist på bättre vetande.

Public Function ExecuteSQL(Optional ByRef rsObject As Recordset) As Long
On Error Goto fn_Err
  Dim objConn As New ADODB.Connection
  [b]Dim blnOpenRS As Boolean

  blnOpenRS = false[/b]

  Set objConn = connection...
  Set rsObject = New ADODB.Recordset

  If InStr("DELETE", strSQL) Or InStr("INSERT INTO", strSQL) Then
    objConn.Execute strSQL, lngRecordsAffected, adExecuteNoRecords
    
    ExecuteSQL = lngRecordsAffected
  ElseIf InStr("SELECT", strSQL) Then
    rsObject.Open strSQL, objConn, adOpenForwardOnly, adLockReadOnly
    [b]blnOpenRS = True[/b]
    ExecuteSQL = rsObject.RecordCount
  Else
    MsgBox "Ofärdig SQL-funktion..."
  End If

fn_Exit:
    [b]If blnOpenRS then rsObject.Close[/b]
    Set rsObject = Nothing
    objConn.Close: Set objConn = Nothing
    Exit Function

fn_Err:
    g_intErrNum = Err.Number
    g_strErrDesc = Err.Description
    g_strErrorMsg = FormatSQL((strSQL))
    g_strFunctionName = "ExecuteSQL"
    g_strSourceName = "modGlobalaFunktioner"
    
    Call g_ErrorHandler
    Resume fn_Exit
End Function

Det finns säkert bättre sätt att lösa det på, men jag gillar de enkla lösningarna. ;)

Mvh

Medlem sedan dec. 20003 887 inlägg
#3

Ok... det måste ju fortfarande vara alldeles för tidigt på dan, eftersom den enkla lösningen aldrig infann sig i mitt huvud :OO

Medlem sedan dec. 20003 887 inlägg
#4

Nya problem :)

Mitt ByRef-recordset försvinner. Varför gör det det? Bör inte ByRef ordna så att det inte försvinner?

Medlem sedan juni 200032 967 inlägg
#5

Följdfrågor:

  1. Vad då försvinner?
  2. Skickar du in det som ett recordsetobjekt i funktionen? Då behöver du inte skapa det med Set i funktionen.
  3. Vem är det som kallar på funktionen? En annan VB-funktion?

Mvh

Medlem sedan dec. 20003 887 inlägg
#6

1. Tja... objektet existerar inte efter att funktionen är klar
2. Jupp... Set försvinner
3. Japp

Private Sub Fiffel()
  Dim rsThis As New ADODB.Recordset

  ExecuteSQL rsThis

  rsThis(0) <-- Error...
End Sub
Medlem sedan juni 200032 967 inlägg
#7

Du stänger och förstör ju objektet inne i funktionen, så det är inte så konstigt att det inte existerar efter det att du kört funktionen heller. :)

Mvh

Medlem sedan dec. 20003 887 inlägg
#8

Jo, jag är medveten om det, men jag fick för mig att byref skulle ta hand om det åt mig... hur gör jag då? Måste funktionen returnera ett recordset för att det ska fungera som jag vill?

Medlem sedan juni 200032 967 inlägg
#9

Nej, du ska ge 17 i att stänga och förstöra det inne i ExecuteSQL() bara.

Jämför:

' skriv sql-fråga
' skapa recordset
' exekvera sql-fråga, fyll recordset
' stäng och förstör recordset
' försök hämta saker från recordsetet som inte längre finns

Att du gör det i en funktion med ett ByRef-objekt är precis samma som att göra det i den kallande funktionen. Du kan inte använda ett objekt som inte finns liksom. ;)

Så, antingen ser du till att returnera recordsetet från funktionen istället för att använda ByRef, eller så ser du till att inte göra dig av med recordsetet inne i ExecuteSQL(). Jag hade gjort det sistnämnda.

Mvh

Medlem sedan dec. 20003 887 inlägg
#10

Jag som trodde att jag var något smart på spåret, men det kan jag lugnt konstatera att det var bara vad jag trodde... :)

Det känns dock som om jag kommer till att få objekt som ligger och skräpar här och var om jag inte ser till att hålla tungan rätt i munnen...

Medlem sedan dec. 20003 887 inlägg
#11

Ok. Nu ser det ut som följer, och det fungerar förvisso

Public Function ExecuteSQL() As ADODB.Recordset
On Error GoTo fn_Err
    Dim objConn As New ADODB.Connection
    
    Set ExecuteSQL = New ADODB.Recordset
    
    objConn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Lager\Lager.Back-End.dev.mdb;Mode=Share Deny None"
    
    If InStr(strSQL, "INSERT INTO") Or InStr(strSQL, "DELETE FROM") Then
        objConn.Execute strSQL, lngRecordsAffected, adExecuteNoRecords
        
        Set ExecuteSQL = Nothing
    ElseIf InStr(strSQL, "SELECT") Then
        ExecuteSQL.Open strSQL, objConn, adOpenForwardOnly, adLockReadOnly
    Else
        MsgBox "Okänd SQL-fråga." & vbCrLf & vbCrLf & FormatSQL(strSQL), vbExclamation, "Fel!"
    End If
End Function

Men kommer inte det att orsaka minnesläckage? (Hemska tanke)

Medlem sedan juni 200032 967 inlägg
#12

Om du låter ExecuteSQL-funktionen se ut så här:

Public Function ExecuteSQL(Optional ByRef rsObject As Recordset) As Long
On Error Goto fn_Err
  Dim objConn As New ADODB.Connection

  Set objConn = connection...
  Set rsObject = New ADODB.Recordset

  If InStr("DELETE", strSQL) Or InStr("INSERT INTO", strSQL) Then
    objConn.Execute strSQL, lngRecordsAffected, adExecuteNoRecords
    
    ExecuteSQL = lngRecordsAffected
  ElseIf InStr("SELECT", strSQL) Then
    rsObject.Open strSQL, objConn, adOpenForwardOnly, adLockReadOnly
    ExecuteSQL = rsObject.RecordCount
  Else
    MsgBox "Ofärdig SQL-funktion..."
  End If

fn_Exit:
    objConn.Close: Set objConn = Nothing
    Exit Function

fn_Err:
    g_intErrNum = Err.Number
    g_strErrDesc = Err.Description
    g_strErrorMsg = FormatSQL((strSQL))
    g_strFunctionName = "ExecuteSQL"
    g_strSourceName = "modGlobalaFunktioner"
    
    Call g_ErrorHandler
    Resume fn_Exit
End Function

, och använder ditt ByRef-recordset så borde du inte få några skräpande objekt. Däremot kan det vara så att du måste byta cursorlocation/cursortyp för att inte förstörandet av ditt connectionobjekt ska riva med sig recordsetet.

Mvh

Medlem sedan juni 200032 967 inlägg
#13

Jag hade nog hellre gjort så här:

Public Function ExecuteSQL() As ADODB.Recordset
On Error GoTo fn_Err
    Dim objConn As New ADODB.Connection
    
    [b]Set objTempRS = New ADODB.Recordset[/b]
    
    objConn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Lager\Lager.Back-End.dev.mdb;Mode=Share Deny None"
    
    If InStr(strSQL, "INSERT INTO") Or InStr(strSQL, "DELETE FROM") Then
        objConn.Execute strSQL, lngRecordsAffected, adExecuteNoRecords
        
        Set ExecuteSQL = Nothing
    ElseIf InStr(strSQL, "SELECT") Then
        [b]objTempRS[/b].Open strSQL, objConn, adOpenForwardOnly, adLockReadOnly
    Else
        MsgBox "Okänd SQL-fråga." & vbCrLf & vbCrLf & FormatSQL(strSQL), vbExclamation, "Fel!"
    End If
[b]    Set ExecuteSQL = objTempRS
    objTempRS.Close : Set objTempRS = Nothing
    objConn.Close : Set objConn = Nothing[/b]
End Function

Då borde du inte få några läckor / objekt som skräpar.

Mvh

Medlem sedan dec. 20003 887 inlägg
#14

Det var då väldigt knivigt att hantera connectionobjektet :l

Samtidigt passade tiden på att rinna iväg :( Jag lär försöka mer med det här någon gång framöver.

Medlem sedan juni 200032 967 inlägg
#15

Vad är det som är knivigt? Provade du mitt sista förslag? Är det icke godtagbart?

Mvh

Medlem sedan dec. 200012 464 inlägg
#16

Flyttas från ASP

277 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
126 ms — deklarationer (db)
0 ms — hämta statistik (cache)
147 ms — hämta tråd, inlägg och bilagor (db)
121 ms — ändringar (db)