[ASP.NET] Teveel connecties met SQL

Pagina: 1
Acties:

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 20-05 23:28
Op een aspx pagina, worden gegevens uit een database gehaald.

Als ik ervoor zorg dat hij 1 query uitvoert, kan ik 60 keer de page refreshen, en daarna zegt komt hij met een object reference fout.

Als ik de een SQL commando 60 keer uitvoer in 1 pageload, gebeurt hetzelfde.
In het SQL commando wordt de Connectie geopend, en als laatste gesloten.
code:
1
2
3
4
5
6
7
8
9
10
var command    : BdpCommand;
begin
    Connection.open;
    command := connection.CreateCommand;
    command.Connection := Connection;
    command.CommandText := SQLcommand;
    data := command.ExecuteReader;
    command.free; // moet free zijn anders geen output !!!!
    connection.close;
end;


Wat gaat hier aan fout? Ik krijg wel netjes mijn gegevens op het scherm.
Connection.Dispose heb ik ook al geprobeerd.
En ik had ook eerst:
code:
1
command := BdpCommand.Create;
in plaats van:
code:
1
command := connection.CreateCommand;


Als ik bij 1 pageload 1 keer de connectie open en 1 keer sluit,
en veel SQL commando's uitvoer krijg ik:

Execute failed. SQL State: 3014, SQL Error Code: -85853471 Kan niet meer tabellen openen.

Ik ben al een tijd bezig en met 2 man al aan het probleem aan het werken maar we komen er niet uit. :(

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 15:50

gorgi_19

Kruimeltjes zijn weer op :9

Je sluit data niet af, sluit die ook eens af?

[ Voor 38% gewijzigd door gorgi_19 op 23-07-2004 16:55 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Zou ASP geen garbage collection moeten uitvoeren?

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 15:50

gorgi_19

Kruimeltjes zijn weer op :9

Verwijderd schreef op 23 juli 2004 @ 16:56:
Zou ASP geen garbage collection moeten uitvoeren?
Ja, mits je de connectie niet meer gebruikt. Als je hem open laat, heeft hij ook niets te collecten, want dan is hij nog in gebruik.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Als dat zo is, dan missen ze bij ASP het hele punt van garbage collection.

Want, zodra een variabele out of scope gaat, kun je 'm nooit meer terug krijgen. (Uiteraard, als hij niet gekopiëerd is in tussentijd, dus als z'n refcount 0 is, I know, moving along...).

Die variabele is dus zojuist nutteloos geworden, en moet dus opgeruimd worden, of er nou een db-connection aan hangt of niet. En juist als er een database connection aan hangt (of een andere resource), moet die opgeruimd worden, omdat je anders al je resources verbruikt.


Het hele punt van GC is nou net dat je niet op opruimen/dealloceren/vrijgeven hoeft te letten... :/

  • Rolgordijn
  • Registratie: Januari 2000
  • Laatst online: 30-06-2022
Het hele punt van GC is nou net dat je niet op opruimen/dealloceren/vrijgeven hoeft te letten... :/
Het hele punt van GC is dat je minder op vrijgeven van resources hoeft te letten. Het is niet zo dat je alle destructieregels zomaar kan laten varen.

Bij non-managed resources dient de programmeur er altijd voor te zorgen dat het object wordt opgeruimd, daarom bestaat de IDisposable interface ook. Als een object deze interface implementeerd dien je gewoon Dispose() aan te roepen wanneer je klaar bent met het object. En als je wil voorkomen dat je dat vergeet gebruik je gewoon een using(...) {} statement.

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 20-05 23:28
gorgi_19 schreef op 23 juli 2004 @ 16:55:
Je sluit data niet af, sluit die ook eens af?
Sorry, je hebt wel gelijk, maar dat gebeurt ergens anders in de source.
Ben dat vergeten te vermelden.

Het maakt overigens niet uit welk server programma gebruikt wordt.
Op de PC waar het uiteindelijk draait is dit IIS, en op testPC is dat Casini.

Als database wordt een MS ACCESS database gebruikt.

Misschien dat de drivers brak zijn???

[ Voor 20% gewijzigd door Cheater op 25-07-2004 15:00 ]


Verwijderd

Cheater schreef op 23 juli 2004 @ 16:53:
Als ik de een SQL commando 60 keer uitvoer in 1 pageload, gebeurt hetzelfde.
In het SQL commando wordt de Connectie geopend, en als laatste gesloten.
code:
1
2
3
4
5
6
7
8
9
10
var command    : BdpCommand;
begin
    Connection.open;
    command := connection.CreateCommand;
    command.Connection := Connection;
    command.CommandText := SQLcommand;
    data := command.ExecuteReader;
    command.free; // moet free zijn anders geen output !!!!
    connection.close;
end;
Andere opmerking...
Als je "command.free" doet, ben je dan niet ook je data kwijt?

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 20-05 23:28
Verwijderd schreef op 23 juli 2004 @ 22:31:
Andere opmerking...
Als je "command.free" doet, ben je dan niet ook je data kwijt?
Nee. De opmerking achter het commando heb ik gedaan
omdat als ik command.CLOSE doe, ik juist DAN m'n data kwijt ben.
Om eerlijk te zijn, dat gaat me een beetje logisch lijken.
Zo van:

- Eerst doen met m'n datareader doen wat ik wil
- datareader closen if not IsClosed + Free desnoods
- command.free

zou hier dan na het connection.close komen?
Ik weel dat de DataReader een live capture van de output is, en dat je deze kwijt bent na het closen, en dat het een forward-only pointer is.

We hebben al zoveel geprobeerd, en zoveel documentaties gelezen... ten einde raad dus.

  • Rolgordijn
  • Registratie: Januari 2000
  • Laatst online: 30-06-2022
Je maakt momenteel gebruik van een DataReader, een DataReader is een forward-only stream, wat inhoudt dat hij over de geopende database connectie door je resultaatset bladert.

een quote uit de Framework SDK
While the SqlDataReader is in use, the associated SqlConnection is busy serving the SqlDataReader, and no other operations can be performed on the SqlConnection other than closing it. This is the case until the Close method of the SqlDataReader is called. For example, you cannot retrieve output parameters until after you call Close.
Als je er voor wil zorgen dat je de database connectie zo kort mogelijk openhoudt, zodat deze connectie weer beschikbaar gesteld wordt aan de connection pool, is het gebruik van DataSet's aan te raden. Deze biedt een disconnected, in-memory, representatie van je resultset (en meer, sla er de SDK maar ff op na).

Verwijderd

Cheater schreef op 23 juli 2004 @ 22:37:
[...]


Nee. De opmerking achter het commando heb ik gedaan
omdat als ik command.CLOSE doe, ik juist DAN m'n data kwijt ben.
Om eerlijk te zijn, dat gaat me een beetje logisch lijken.
Zo van:

- Eerst doen met m'n datareader doen wat ik wil
- datareader closen if not IsClosed + Free desnoods
- command.free

zou hier dan na het connection.close komen?
Ik weel dat de DataReader een live capture van de output is, en dat je deze kwijt bent na het closen, en dat het een forward-only pointer is.

We hebben al zoveel geprobeerd, en zoveel documentaties gelezen... ten einde raad dus.
Kun je dan niet beter een DataSet gebruiken?'
Want zoals je de code zo hebt neergezet, zou je volgens mij "alles kwijt" moeten zijn na het sluiten van de database.

  • Not Pingu
  • Registratie: November 2001
  • Laatst online: 01-04 20:36

Not Pingu

Dumbass ex machina

with ^^

De functie van een datareader is nou eenmaal dat ie een connectie naar de database houdt: het is een soort stream. Als je data echt wilt ophalen om mee te werken, gebruik dan een SQLDataAdapter ipv. een SQLCommand.

code:
1
2
3
4
5
6
Dim myConn As New SqlConnection(connectionString)
myConn.Open()
Dim myDataAdapter As New SqlDataAdapter(SqlQuery, myConn)
Dim myDataSet As New DataSet
myDataAdapter.Fill(myDataSet)
myConn.Close()


Zo kun je ook data returnen vanuit een DAL klasse. Met DataReaders gaat dat echt niet lukken.

De reden dat ASP.Net een DataReader niet opruimt is denk ik omdat ie dan nog steeds in gebruik is als je em niet sluit.

Certified smart block developer op de agile darkchain stack. PM voor info.


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 15:50

gorgi_19

Kruimeltjes zijn weer op :9

TS:
Waar bind je data aan? Wat gebeurd er mee? Aangezien ik m'n twijfels heb of deze wel goed wordt afgesloten.
Gunp01nt schreef op 24 juli 2004 @ 00:11:
Zo kun je ook data returnen vanuit een DAL klasse. Met DataReaders gaat dat echt niet lukken.
Je kan Datareaders perfect gebruiken in je DAL class, mits je deze gebruikt om custom objects terug te geven. Deze vind ik zelf fijner werken dan een (typed) dataset.
Verwijderd schreef op 23 juli 2004 @ 17:25:
Als dat zo is, dan missen ze bij ASP het hele punt van garbage collection.
Afaik heeft een Datareader een active connection nodig en is het een soortement van 'stream'. Je zult dus handmatig een einde moeten definieren. Wil je dit niet, dan is er een datatable / dataset; iets meer overhead dan een datareader, maar dan heb je dit probleem niet.

[ Voor 11% gewijzigd door gorgi_19 op 24-07-2004 00:56 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 20-05 23:28
Ja, denk eens na over het volgende:

Een DataSet kan GEEN memo veld uitlezen uit de database. Dat is het nadeel. Mijn collega heeft dit nagekeken.

Nee DataSet valt helaas af.

OnTopic:
Na het lezen van de reacties kom ik tot de conclusie (wat ik in principe zo ook had kunnen bedenken, althans dat lag voor handen)

is dat ik mijn command class NIET goed sluit
(free is te ruw en ruimt niet AL zijn resources op denk ik en het moet dus een close of dispose zijn)

Ik doe nu een Free, omdat ik anders niks meer met de datareader kan doen (geen data meer). Het klinkt dan ontzettend logisch dat ik:
command + connectie sluit na het closen van de BdpDataReader (wat ook altijd moet gebeuren!)

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 15:50

gorgi_19

Kruimeltjes zijn weer op :9

Memo fields wel eens van gehoord dat ze kunnen etteren, alleen dat ze het volledig niet doen, heb ik nog niet van gehoord. Heb je je memofield achteraan je select query gezet, dat wil nog wel eens helpen.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Cheater schreef op 23 juli 2004 @ 22:37:
[...]

Nee. De opmerking achter het commando heb ik gedaan
omdat als ik command.CLOSE doe, ik juist DAN m'n data kwijt ben.
Om eerlijk te zijn, dat gaat me een beetje logisch lijken.
Zo van:

- Eerst doen met m'n datareader doen wat ik wil
- datareader closen if not IsClosed + Free desnoods
- command.free

zou hier dan na het connection.close komen?
Ik weel dat de DataReader een live capture van de output is, en dat je deze kwijt bent na het closen, en dat het een forward-only pointer is.

We hebben al zoveel geprobeerd, en zoveel documentaties gelezen... ten einde raad dus.
Zoals al eerder gezegd kan je ook het command-object niet sluiten als deze nog in gebruik is door de datareader. Ik weet niet wat er gebeurt met geheugen allocatie en geheugenbeheer als je Free gebruikt. Wat ik wel weet is dat er nog een referentie is vanuit de datareader naar het command-object toe.

Het commentaar wat je geeft op de command.free is trouwens nogal discutabel.
Hoe lees je de data uit?
code:
1
2
3
4
5
6
7
if (data.HasRows()) then
begin
  while (data.GetRows())
  begin
    //
  end;
end;


Wat jij wilt kan gewoon niet op deze manier. Dat komt voornamelijk door regel 8 en 9 die de boel in de war schoppen.

Ik zou in de onload de connectie met de database maken en in de onunload de connectie met de database sluiten (zijn dit de beste events?)


BTW.
Een Command hoef je toch niet vrij te geven? Een DataReader volgens mij wel als deze data bevat?

[ Voor 5% gewijzigd door Verwijderd op 24-07-2004 23:28 ]


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 15:50

gorgi_19

Kruimeltjes zijn weer op :9

Een Command hoef je toch niet vrij te geven? Een DataReader volgens mij wel als deze data bevat?
Normaliter sluit je zowel de datareader als de bijbehorende connection. :)

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 20-05 23:28
gorgi_19 schreef op 25 juli 2004 @ 00:05:
[...]

Normaliter sluit je zowel de datareader als de bijbehorende connection. :)
Ja inderdaad. Dat deed ik al. Alleen m'n bdpCommand sluit ik niet op de goede manier. (en als ik het wel op de goede manier doe heb ik geen verbinding naar de data meer. wat dus logisch is!)

Mijn vraag nu dan eigenlijk is: Hoe komt het dat het niet vrijgeven (closen / disposen) van een BdpCommand de webserver zo in de boel kan schoppen?

Het legt namelijk zowel Casini als IIS plat.
Of moet ik het zien als: De Access Database accepteerd maximaal 60 open tabellen?

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 15:50

gorgi_19

Kruimeltjes zijn weer op :9

Of moet ik het zien als: De Access Database accepteerd maximaal 60 open tabellen?
Ik gok eerder dat je een maximale connection pool hebt die leeg begint te raken, maar zeker durf ik dit niet te zeggen. :) Sowieso is MS Access niet dol op een webomgeving, maar da's een andere discussie :)

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Cheater schreef op 25 juli 2004 @ 13:25:
[...]

Ja inderdaad. Dat deed ik al. Alleen m'n bdpCommand sluit ik niet op de goede manier. (en als ik het wel op de goede manier doe heb ik geen verbinding naar de data meer. wat dus logisch is!)
Volgens mij is dat helemaal niet logisch. Want wat ik zelf ondervonden heb (als ik het goed heb) zou je een Command niet mogen wijzigen als deze nog gekoppeld is aan een datareader. Tenminste, dat is zo bij een SQLCommand. Grote kans dat dit bij een bdpCommand ook zo is.

Wellicht gaat het daar mis. Je hele methodiek moet gewoon op de schop.

Connection -> Command -> DataReader
Cheater schreef op 25 juli 2004 @ 13:25:

Mijn vraag nu dan eigenlijk is: Hoe komt het dat het niet vrijgeven (closen / disposen) van een BdpCommand de webserver zo in de boel kan schoppen?

Of moet ik het zien als: De Access Database accepteerd maximaal 60 open tabellen?
Ik denk ook dat op een gegeven moment ook het maximum van de connection pool bereikt wordt.

Ik zou het volgende ff testen in een functie.

- Connectie openen
- Command aanmaken
- Command vullen met juiste query, connectie, etc.
- Command uitvoeren met resultaat naar DataReader.
- DataReader uitlezen. (doe iets met data)
- DataReader closen.
- Connectie closen.

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 20-05 23:28
Verwijderd schreef op 26 juli 2004 @ 00:00:Ik zou het volgende ff testen in een functie.

- Connectie openen
- Command aanmaken
- Command vullen met juiste query, connectie, etc.
- Command uitvoeren met resultaat naar DataReader.
- DataReader uitlezen. (doe iets met data)
- DataReader closen.
- Connectie closen.
Je beschrijft eigenlijk precies wat in m'n TS staat. En mis het vrijgeven van command in je lijstje. Waar het in principe om ging voor de helft in de discussie tot nu toe.

Verwijderd

Cheater schreef op 26 juli 2004 @ 11:57:
[...]


Je beschrijft eigenlijk precies wat in m'n TS staat. En mis het vrijgeven van command in je lijstje. Waar het in principe om ging voor de helft in de discussie tot nu toe.
Nee, jij wilt in principe na al deze stappen, nog de data uit kunnen lezen! En dat kan dus niet.
Mijn doel was dat je met deze testopzet ff gaat testen of het probleem dan nog steeds optreedt.

Het gebruik van Dispose() schijnt niet relevant te zijn.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Ze gaan daar wel wat kort door de bocht. Close() released een connectie terug de Connection Pool in, waardoor de connectie gerecycled wordt indien er een nieuwe SqlConnection met dezelfde string wordt geopend. Dispose() daarentegen knikkert de hele connectie op slot en is dus in een zwaarbeladen applicatie trager.

Professionele website nodig?


Verwijderd

curry684 schreef op 26 juli 2004 @ 17:02:
[...]

Ze gaan daar wel wat kort door de bocht. Close() released een connectie terug de Connection Pool in, waardoor de connectie gerecycled wordt indien er een nieuwe SqlConnection met dezelfde string wordt geopend. Dispose() daarentegen knikkert de hele connectie op slot en is dus in een zwaarbeladen applicatie trager.
Als we terug gaan naar het Command-object...

Deze heeft geen Close() functie, maar wel een Dispose()?!
Moeten we Dispose() gebruiken om resources vrij te geven, na het gebruik van het Command object? Of regelt de Garbage collector dit?

  • mindcrash
  • Registratie: April 2002
  • Laatst online: 22-11-2019

mindcrash

Rebellious Monkey

Verwijderd schreef op 26 juli 2004 @ 19:14:
[...]

Als we terug gaan naar het Command-object...

Deze heeft geen Close() functie, maar wel een Dispose()?!
Moeten we Dispose() gebruiken om resources vrij te geven, na het gebruik van het Command object? Of regelt de Garbage collector dit?
De GC gooit inderdaad na een bepaalde tijd de objecten die niet meer gebruikt worden weg. Het is daarom beter om dit zelf te doen omdat de connectionpool nog weleens wil vollopen als je dit niet doen en er simpelweg vanuit gaat dat de GC wel je rommel netjes opruimt. Altijd Dispose() doen als je objecten niet meer gebruikt is dus wel zo netjes ;)

[ Voor 7% gewijzigd door mindcrash op 26-07-2004 20:31 ]

"The people who are crazy enough to think they could change the world, are the ones who do." -- Steve Jobs (1955-2011) , Aaron Swartz (1986-2013)


  • Rolgordijn
  • Registratie: Januari 2000
  • Laatst online: 30-06-2022
Het gaat er niet alleen om dat het 'netjes' is, het gaat er om dat de IDisposable interface aangeeft dat het van de programmeur wordt verwacht.

Of zoals in Essential .NET Volume 1: The CLR (blz 150) wordt beschreven:
Classes that implement this interface are indicating that they require explicit cleanup. It is ultimately the client programmer's responsibility to invoke the IDisposable.Dispose method as soon as the referenced object is no longer needed.

Verwijderd

craze schreef op 26 juli 2004 @ 21:13:
Het gaat er niet alleen om dat het 'netjes' is, het gaat er om dat de IDisposable interface aangeeft dat het van de programmeur wordt verwacht.

Of zoals in Essential .NET Volume 1: The CLR (blz 150) wordt beschreven:

[...]
F1 --> MSDN

.NET Framework Class Library
SqlCommand.IDisposable.Dispose Method
Note: This namespace, class, or member is supported only in version 1.1 of the .NET Framework.
This member supports the .NET Framework infrastructure and is not intended to be used directly from your code.


?!?

[ Voor 3% gewijzigd door Verwijderd op 26-07-2004 21:19 ]


  • Rolgordijn
  • Registratie: Januari 2000
  • Laatst online: 30-06-2022
Je maakt het allemaal moeilijker en onduidelijker dan het is hoor. Je kijkt nu gewoon naar de verkeerde method; de method die je aanhaalt is namelijk een private method, niet de public method die door de Interface wordt geboden.

Bekijk de MSDN documentatie van de IDisposable Interface maar even, dan zie je hoe dat het verwacht wordt dat je hem implementeerd.
Pagina: 1