2009-06-06 13 views
6

In Java e C#, entrambi hanno qualcosa come System.terminate(). Se il mio programma ha connessioni di database aperte, lettori di database e variabili di comando del database e interrompo il mio programma in una clausola catch, le risorse del database rimarranno ancora in uso? o saranno liberati automaticamente da quando il mio intero programma è appena uscito?Se un programma di console termina, le connessioni al database utilizzate nel programma rimarranno ancora aperte?

Normalmente, come devo gestire tali casi per assicurarmi di avere sempre connessioni di database libere, sia attraverso la normale chiusura del programma o la chiusura inaspettata del programma? Qualche buona pratica?

risposta

0

In C#, è di norma stretti legami subito dopo il loro utilizzo, ad esempio:

using(SqlConnection connection = ...) 
{ 
    ... do something ... 
} // connection disposed/closed here 

Tuttavia, in genere si utilizzerà un pool di connessioni, e tutto ciò viene effettuato restituisce la connessione al pool. Quindi il tuo processo avrà ancora connessioni attive al server del database.

Se si chiude in modo pulito, il pool di connessioni verrà senza dubbio ripulito e le connessioni effettive al database verranno chiuse (è possibile verificare ciò osservando le connessioni aperte sul server di database).

Ma ci sono situazioni (ad esempio chiamate Environment.FailFast) in cui l'applicazione potrebbe bloccarsi senza chiudere le connessioni - in questo caso alla fine scadranno e verranno chiuse dal server del database.

+0

È possibile espandere il pool di connessioni? E come li avrei implementati? – Saobi

5

A meno che non si chiuda specificamente la connessione, rimarranno aperti fino a quando non si verifica un timeout.

Ho trovato questo fuori nel modo più difficile in C# un paio di volte. Le migliori pratiche dettano lo spegnimento/la chiusura di risorse che sai che non ti serviranno più. File I/O stream, connessioni DB, ecc. Ecc.

+0

È vero anche se l'applicazione si arresta in modo anomalo? (Non essendo faceto, solo curioso) –

+1

Lo immaginerei. Voglio dire, se hai un try/catch e sei nel mezzo di modificare un file e io strattone il cavo di alimentazione. Questi salvataggi andranno persi nel limbo .... –

+0

Penso che questo dipenda dal tipo di incidente. Alcuni arresti anomali possono influire sul tempo di esecuzione (come strappare il cavo di alimentazione, sovraccaricare lo stack, ecc.) In tal caso, la connessione rimarrà aperta fino al raggiungimento del timeout. Se però viene lanciata una semplice eccezione, penso che il runtime cercherà comunque di chiudere la connessione (se in un blocco "finally") –

6

Al termine di un processo, tutte le risorse associate (inclusi memoria, handle, connessioni, ...) verranno liberate.

Normalmente, in C#, verrà utilizzato il modello Dispose/using per controllare le risorse scarse.

+1

Per quanto ne so, credo che tu abbia ragione. Quello che trovo curioso è che PSU_Kardi afferma il contrario e ha più upvotes. Allora, chi è giusto? –

+0

@MasterPeter: questa è sicuramente una cosa dipendente dalla piattaforma. Ma sulla maggior parte dei sistemi principali che ho visto, questo è il caso. –

+0

Errore errato corretto dell'ordine. –

-1

Deve essere cancellato sul prossimo GC, ma per essere precisi, in C# è possibile chiudere la connessione sul blocco finally della gestione delle eccezioni strutturate.

try { 
    // open DB connection 
} catch (Exception ex) { 
    // deal with exception 
} finally { 
    // close and dispose connection 
} 
+0

Ok. ma cosa succede se ho delle istruzioni di connessione db sparse per tutto il mio programma, così che non riesco a metterle insieme in una prova/cattura/finalmente. Dovrei semplicemente mettere il mio INTERO programma in un blocco grande try/catch/finally, quindi ogni volta che si verifica un errore imprevisto il mio db sarà chiuso? Ma mettere tutto in una grande prova/cattura/finalmente non è elegante? – Saobi

+0

Errr ... dove si trova il GC quando il processo non esiste? –

+1

Saobi: dovresti dividere il codice DB in blocchi più gestibili e mettere il blocco try/catch su ciascuno. Curt: questo è PRIMA che il processo esca, meglio che terminare semplicemente il processo perché non si può garantire che la terminazione anomala chiuderà sempre la connessione. –

0

Il comportamento generale POSIX è che, quando il programma termina, tutti gli handle di file, connessioni di rete e così via sono chiusi. Se l'altro capo fa la cosa giusta a quel punto è una domanda aperta, ma se stai usando qualsiasi RDBMS ragionevolmente popolare, andrà bene.

1

In C#, la pulizia implicita viene eseguita dal garbage collector se un finalizzatore è implementato nell'oggetto che viene sottoposto a garbage collection. Qualsiasi pulizia delle risorse non gestite, come le connessioni al database, può essere eseguita nel metodo Dispose.

veda questo articolo per maggiori informazioni:

Implementazione Finalizza e Dispose per pulire non gestito risorse
http://msdn.microsoft.com/en-us/library/b1yfkh5e(VS.71).aspx

1

Quando un processo termina, tutti i descrittori di file che ha aperto devono essere rilasciati dal sistema operativo. I descrittori di file includono file e socket, che generalmente coprono le connessioni del database.

Tutto ciò che ti dice è che quando il tuo client termina le sue connessioni sono chiuse. Non ti dice cosa fa il server. A seconda di come è scritto, è del tutto possibile che il server continui a tenere aperte le sue connessioni, aspettandosi messaggi dal client che non arriverà mai, o addirittura tentando di inviare dati. Probabilmente alla fine avranno probabilmente un timeout, ma potrebbe non essere ben pianificato. (Dovrebbe essere, per un RDBMS decente, ma potrebbe non esserlo.) Quindi, a seconda del tuo RDBMS, potrebbe essere necessario prendere alcune misure per dire al server che stai andando giù per dirgli di rilasciare le sue risorse.

1

Se si sta lavorando con SQL Server è possibile dare un'occhiata al sysprocesses o eseguire sp_who2. Ho provato questo sulla mia macchina e le connessioni si ottiene chiuso, vale a dire:

Console.Write("Opening connection"); 
Console.ReadLine(); 
SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=SeniorMail;Integrated Security=SSPI;"); 
connection.Open(); 
SqlCommand command = new SqlCommand("SELECT count(*) from Account", connection); 
Console.Write("Running sql"); 
Console.ReadLine(); 
int? count = command.ExecuteScalar() as int?; 
Console.Write("Now I'll throw an exception"); 
Console.ReadLine(); 
int a = 0, b = 1, c = 0; 

try 
{ 
    c = b/a; 
} 
catch 
{ 
    Environment.Exit(1); 
} 

Ho controllato sp_who2 entrambi i lati di "Ora ti faccio un'eccezione", e posso vedere la connessione è scomparso dopo l'applicazione uscite.

Problemi correlati