webForumDet fria alternativet

stänga SqlConnection

14 svar · 322 visningar · startad av renholm

renholmMedlem sedan apr. 20012 048 inlägg
#1

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
#2

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
#3

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
#4

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
#5

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
#6

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
#7

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
#8

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
#9

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
#10

Jo, det stämmer ju.

fredrikMedlem sedan dec. 19991 082 inlägg
#11

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
#12

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
#13

Ä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
#14

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
#15

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.

Genererad på 378 ms · cache AV · v20260730165559-full.f96bc7eb