renholmMedlem sedan apr. 20012 048 inlägg
Hur bör man göra för att stänga databasconnections för att inte ta upp connection pool?
SqlDataReader.Close?
SqlCommand.Dispose?
Har fått detta error ett flertal gånger.
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Jag har ett eget databas objekt som jag använder varje gång något ska hämtas.
Public Class dbObject
Private connectionString As String
Protected Connection As SqlConnection
Public Sub New(ByVal newConnectionString As String)
connectionString = newConnectionString
Connection = New SqlConnection(connectionString)
End Sub
Public Function RunProcedure(ByVal storeProcName As String) As SqlDataReader
Dim objCmd As SqlCommand = New SqlCommand(storeProcName, Connection)
Dim objReader As SqlDataReader
objCmd.CommandType = CommandType.StoredProcedure
Connection.Open()
objReader = objCmd.ExecuteReader(CommandBehavior.CloseConnection)
objCmd.Dispose()
Return objReader
End Function
End Class
fredrikMedlem sedan dec. 19991 082 inlägg
Du måste göra ".Close" och även sätta till "Nothing", alltså 3 saker:
1. "Connection.Close()"
2. "Connection.Dispose()"
3. "Connection = Nothing"
Så fort ett objekt har en "Dispose"-metod så ska den anropas, alla objekt ska även alltid sättas till "Nothing".
Readern borde stänga Connection i ditt fall..men det är kanske inte helt att lita på...
renholmMedlem sedan apr. 20012 048 inlägg
precis, jag satt med Performance programet o kikade på hur många ConnectionPools den gick upp vid varje sid laddning, märkte att den i visa fall bara gick upp direkt efter kompilering av projekt.
renholmMedlem sedan apr. 20012 048 inlägg
Har rätt stora problem med detta. Jag övervakar "Current # pooled connection" i Performance och varje gång jag laddar om första sidan efter jag kompilerat om den, så går "Current # pooled connection" upp 2 steg, för tillfället ligger den på 220 men igår 720 så vi rebootade servern. Problemet verkar vara att kopplingen inte stängs. Jag kan inte använda SqlConnection.Close i min RunProcedure function eftersom om jag lägger in den innan Return så får jag "Invalid attempt to Read when reader is closed. ". Så några förslag på vad jag bör göra? eller är det tom. normalt att den går upp och aldrig går ner?
renholmMedlem sedan apr. 20012 048 inlägg
ingen som vet något? något litet tips? börjar bli bråttom :)
i mitt DBObject så kommer aldrig Connection stängas eftersom objReader retuneras, hur ska jag stänga connection då?
och hur gör jag i fall jag har en funktion som retunerar en SqlDataReader som direkt går till DataSource på t.ex. en DataGrid, när stängs den? är anslutningen fortfarande öppen? någon som vet? kanske har något exempel på ett sådant databas objekt som jag skapat men funkar på annat sätt?
fredrikMedlem sedan dec. 19991 082 inlägg
Du kan ju lägga till en egen "Dispose"-metod i din klass där du stänger "Connection". Då får du ropa på den manuellt när du är klar med Readern.
renholmMedlem sedan apr. 20012 048 inlägg
jo, har funderat på sådana lösningar, men tror jag kör med en Arraylist i stället för SqlDataReader. Så i RunProcedure funktionen så fyller jag en ArrayList och retunerar. Bör funka på samma sätt. Frågan är bara hur man fyller arraylisten.
kristofferMedlem sedan juni 20001 266 inlägg
Så fort ett objekt har en "Dispose"-metod så ska den anropas, alla objekt ska även alltid sättas till "Nothing".
Varför tar inte gc hand om objekten då?
SPiNMedlem sedan mars 20005 832 inlägg
Det gör den säkerligen, men det är väl lika bra att frigöra minne manuellt så snabbt som möjligt - när man är klar med objekten/instanserna?
kristofferMedlem sedan juni 20001 266 inlägg
fredrikMedlem sedan dec. 19991 082 inlägg
Det enda som GC gör är ju att frigöra minnet för objektet, sen kanske den kör ".Close" på objektet med i nån intern event...men det är ju inte helt säkert...Problemet här är ju att inte ".Close" körs.
renholmMedlem sedan apr. 20012 048 inlägg
mitt problem är nu löst,
Public Function RunProcedure(ByVal storeProcName As String) As DataTable
Dim objCmd As SqlCommand = New SqlCommand(storeProcName, Connection)
Dim reader As SqlDataReader
objCmd.CommandType = CommandType.StoredProcedure
Connection.Open()
reader = objCmd.ExecuteReader(CommandBehavior.CloseConnection)
Dim NewTable As New DataTable()
Dim Index As Integer
For Index = 0 To reader.FieldCount - 1
Dim dc As New DataColumn()
dc.ColumnName = reader.GetName(Index)
dc.DataType = reader.GetFieldType(Index)
NewTable.Columns.Add(dc)
Next
While reader.Read
Dim NewRow As DataRow = NewTable.NewRow
For Index = 0 To reader.FieldCount - 1
NewRow(Index) = reader.Item(Index)
Next
NewTable.Rows.Add(NewRow)
End While
reader.Close()
objCmd.Dispose()
Connection.Dispose()
Return NewTable
End Function
NickemannenMedlem sedan aug. 20003 524 inlägg
Är detta en funktion för att hämta data med stored procedures ?
eller har jag fattat det fel?..
fredrikMedlem sedan dec. 19991 082 inlägg
Ja, från början var det en metod för att returnera en öppen "DataReader". Nu returneras dock en "Table" med data. (från en SP)
developerMedlem sedan aug. 2001453 inlägg
Jag har inte läst hela inlägget, så jag tänker inte försöka svara i detalj på problemet. Men något att tänka på när det gäller resurser är exception-hantering. Om något går fel i din kod (databasen är tillfälligt nere, du får en timeout etc.) kommer ett exception kastas och då (som din kod ser ut nu) körs inte dina close:ar som ligger i slutet. Lösningen är att lägga en try/finally handler och i din finally-clause göra close/dispose eller vad som nu behövs.
Det finns flera artiklar om exception-hantering på MSDN eller gotdotnet.com, väl värda att läsas eftersom det ger mycket mer feltolerant kod.