Avatar billede rust10 Nybegynder
28. marts 2004 - 13:06 Der er 22 kommentarer og
1 løsning

åbning og lukning af database forbindelser

Jeg sidder og arbejder på en database klasse som tager sig af alt database kommunikation, jeg er lidt i tvivl om hvornår jeg skal åbne og lukke min connection, eller om jeg overhoved skal da det ikke ser ud til at gøre nogen forskel.

Her er lidt kode eksempler:

Jeg laver en connection i starten af min klasse sådan her:

OleDbConnection conn = new OleDbConnection (@"
            Provider = SQLOleDb;
            User Id=xxx;
            Password=xxx;
            Initial Catalog = errorreport;
            Data source = localhost");

Senere ned i klassen har jeg f.eks denne metode:

public string getProjectNames(int cid)
{
    DataSet ds = new DataSet("Projects");
    OleDbDataAdapter da = new OleDbDataAdapter();
    OleDbCommand cmd;
    cmd = new OleDbCommand("getProjectNames" ,conn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@CID", OleDbType.Integer).Value=cid;
    da.SelectCommand = cmd;
    da.Fill(ds,"Project");
    return ds.GetXml();
}

Nu er det at jeg er ved at arbejde lidt med at fange exceptions, og det ser ud til at dataAdapteren selv lukker forbindelsen når noget går galt. Er det rigtigt at jeg slet ikke skal håndtere dette i en catch blok?
Avatar billede arne_v Ekspert
28. marts 2004 - 13:19 #1
Du bør kalde conn.Close når du er færdig med at bruge connection, så
den kan genbruges.

(formentligt betyder det ikke noget for dit program, men en god vane)
Avatar billede rust10 Nybegynder
28. marts 2004 - 13:37 #2
Det ser ikke ud til at der er nogle problemer med at genbruge conn selv om jeg ikke har conn.Close nogle steder. Men tilføjer bare en finally blok med conn.close i.

En anden ting.. burde jeg have min try/catch(Exception) rundt om alt indholdet i metoden som man kan, eller er det fint nok bare at have den rundt om da.Fill(...) ?
Avatar billede rust10 Nybegynder
28. marts 2004 - 13:39 #3
For lige at være sikker.. der er ingen grund til at bruge conn.Open i den metode vel?
Avatar billede arne_v Ekspert
28. marts 2004 - 13:50 #4
Hvis du kun har et fast antal instanser af din klasse har du kun et fast antal
connections.

Men docs er rimelig klar:

If the OleDbConnection goes out of scope, it is not closed. Therefore, you must explicitly close the connection by calling Close or Dispose.
Avatar billede arne_v Ekspert
28. marts 2004 - 13:53 #5
Hvis conn er en instans varianel og den åbned i constructor eller i en
Init/Connect metode som kaldes inden den her metode, så er der ingen grund til at
kalde Open.
Avatar billede arne_v Ekspert
28. marts 2004 - 13:56 #6
(tilbage til Close diskussionen)

Connection bliver først automatisk lukket, når objektet bliver
garbage collectet og der kan gå rimelig lang tid fra at det går
ud af scope til det garbage collectes.
Avatar billede arne_v Ekspert
28. marts 2004 - 13:56 #7
Og et svar
Avatar billede linebille Nybegynder
28. marts 2004 - 14:06 #8
sidder i stadig med de connections? ;-)
Avatar billede rust10 Nybegynder
28. marts 2004 - 14:09 #9
Hmm, vores database klasse er implmenteret med et singleton pattern, så der skulle aldrig være mere end en instans. I toppen af klassen har vi deklareret conn variablen. Vi kalder ikke conn.Open eller close nogle steder lige nu, og det virker efter hensigten. For mig ser det ud som om at når da.Fill(...) køres bliver forbindelsen åbnet automatisk og lukket bagefter, og af en eller anden grund hvis vi f.eks. fremtivinger exception så som at skrive forkert navn på den stored procedure, så lukkes forbindelsen også (pga garbage collectoren?). Men du mener alligevel jeg bør åbne forbindelsen først?

Vil dette her være pænere, eller er conn.Open overflødig?

public string getProjectNames(int cid)
{
    DataSet ds = new DataSet("Projects");
    OleDbDataAdapter da = new OleDbDataAdapter();
    OleDbCommand cmd;
   
    cmd = new OleDbCommand("getProjectNadmes" ,conn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@CID", OleDbType.Integer).Value=cid;
    da.SelectCommand = cmd;
    try
    {
        conn.Open();
        da.Fill(ds,"Project");
    }
    catch(Exception e)
    {
        throw e;
    }
    finally
    {
        conn.Close();
    }
    return ds.GetXml();
}
Avatar billede arne_v Ekspert
28. marts 2004 - 14:19 #10
Hvis der aldrig er mere end en instans så opretter du connection og lukker
den enten aldrig eller først ved app close.
Avatar billede arne_v Ekspert
28. marts 2004 - 14:20 #11
I skal kalde conn.Open en gang - typisk lige efter at have oprettet conn.
Avatar billede arne_v Ekspert
28. marts 2004 - 14:22 #12
Fra docs:

The Fill method retrieves the data from the data source using a SELECT statement. The IDbConnection object associated with the select command must be valid, but it does not need to be open. If the IDbConnection is closed before Fill is called, it is opened to retrieve data, then closed. If the connection is open before Fill is called, it remains open.
Avatar billede arne_v Ekspert
28. marts 2004 - 14:23 #13
Med jere ssetup tror jeg at jeg ville holde den permanent åben.
Avatar billede rust10 Nybegynder
28. marts 2004 - 14:32 #14
Ok, så lige nu åbner og lukker vi så metoden hver gang der er en der tilgår databasen via en metode, hvilket nok ikke er helt optimalt.

Vi skal bare lige have det penslet det lidt mere ud. Vi laver vores conn variable, åbner forbindelsen i konstruktøren og piller ikke mere ved open/close nu, og selv om man måske får en exception et eller andet sted så lukker man ikke ned?
Avatar billede rust10 Nybegynder
28. marts 2004 - 14:37 #15
så lige en sidste ting og du får dine points :-)

Vi har også en metode der benytter sig af "SELECT @@IDENTITY", du har sagt tidligere at den er connection baseret, hvis vi nu gør som vi har sagt før med at holde forbindelsen åben permanent, kan vi så ikke få nogle samtidigheds problemer her, eller er jeg galt på den?
Avatar billede arne_v Ekspert
28. marts 2004 - 14:37 #16
Det vil jeg mene
Avatar billede arne_v Ekspert
28. marts 2004 - 14:42 #17
Det er den også.

Hvis I skal bruge den feature, så skal I enten bruge lock for at synkronisere
brugen af connection eller have en connection per tråd (flytte Open og Close
ind i den metode I bruger).
Avatar billede rust10 Nybegynder
28. marts 2004 - 14:47 #18
Hvis nu man smider "SELECT @@IDENTITY" ind i den stored procedure som laver den identity man vil have fat i, og bruge den som output parameter, er man så kommet uden om problemet?
Avatar billede arne_v Ekspert
28. marts 2004 - 16:22 #19
Hvis du bruger en stored procedure og SCOPE_IDENTITY() i.s.f. @@IDENTITY
burde det aspekt være OK.

Men generelt i en multithreaded context: en connection per tråd der gør noget
Avatar billede rust10 Nybegynder
28. marts 2004 - 17:07 #20
Vi har lidt flere problemer, men opretter et nyt spørgsmål så du kan få lidt flere points
Avatar billede dgivoni Nybegynder
29. marts 2004 - 08:58 #21
Der er et enkelt problem med at bruge den samme aabne connection hele tiden. Det er nemlig ikke muligt at aabne flere DataReaders via samme connection. I modsaetning til et DataSet, saa bliver en DataReader ikke cached, saa den har brug for en forbindelse til databasen.
Det problem ville eksisterer under alle omstaendigheder, men det kan jo vaere I kan finde en design-loesning, der kan haandtere det...
Avatar billede dgivoni Nybegynder
29. marts 2004 - 09:07 #22
For lige at undgaa misforstaaelser, saa mente jeg, at det ikke var muligt at have flere aabne datareaders som benytter samme connection. Man kan selvfoelgelig godt aabne flere via samme connection, hvis man har lukket det forrige foerst... :)
Avatar billede tomjelen Nybegynder
29. marts 2004 - 21:26 #23
Vi fik lidt problemer med OleDbDataReader og transaction håndtering, den var ikke meget for at give slip på vores connection i nogle situationer. Så vi endte bare med at kaste den enkelte værdi vi skulle have fat i, ind i dataset/adapter ligesom eksemplet oven over, i stedet for at bruge readeren.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester