28. marts 2004 - 13:06Der 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?
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(...) ?
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.
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.
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;
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.
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?
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?
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).
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?
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...
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... :)
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.
Synes godt om
Ny brugerNybegynder
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.