Laden...

[Artikel] Ressourcen schonen - Datenbanken richtig öffnen und schließen

Erstellt von .Kai vor 17 Jahren Letzter Beitrag vor 17 Jahren 47.585 Views
.Kai Themenstarter:in
1.130 Beiträge seit 2005
vor 17 Jahren
[Artikel] Ressourcen schonen - Datenbanken richtig öffnen und schließen

Hallo zusammen,

ich habe mich mal hingesetzt und versucht einen kleinen Artikel über den Verbindungsaufbau zu Datenbanken zu schreiben.

Feedback und Verbesserungsvorschläge sind ausdrücklich erwünscht.

Den Artikel gibt es als Dateianhang am Ende dieses Beitrags oder unter der Adresse:
http://www.veloursnebel.de/Artikel/Ressourcen_schonen.pdf

Vielen Dank an Xqgene, der ein wenig Korrektur gelesen hat.

Hinweis von Abt vor 10 Jahren

Das PDF ist nicht mehr über die URL, sondern nur noch im Anhang verfügbar.

M
1.439 Beiträge seit 2005
vor 17 Jahren

Du musst die Exceptions ja nicht unbedingt fangen. Du kannst auch folgenden Code verwenden:


DBConnection con = null;
try {
    con = new DBConnection();
    ...
} finally {
   if (con != null) con.Close();
}

F
529 Beiträge seit 2003
vor 17 Jahren

Nur ein kleiner Punkt:
Exceptions sollten besser direkt am Entstehungsort behandelt werden. Exceptions fressen nämlich Ressourcen wie verrückt. Nimm als Begründung für das Using, dass man nicht das Dispose im Finally vergessen kann oder der wichtige Code nicht so weit auseinandergezogen wird... 😁

Aber sonst ist das meines Wissens alles richtig.

--
mfg
Franknstein

Besuchen sie das VisualC++ - Forum

.Kai Themenstarter:in
1.130 Beiträge seit 2005
vor 17 Jahren

oki, danke für die Korrekturen. Hab die entsprechenden Stellen verbessert.

.Kai Themenstarter:in
1.130 Beiträge seit 2005
vor 17 Jahren

Original von marsgk
Du musst die Exceptions ja nicht unbedingt fangen. Du kannst auch folgenden Code verwenden:

Du hast natürlich Recht. Hab diese Methode ganz außer acht gelassen.

L
497 Beiträge seit 2006
vor 17 Jahren

Bzgl. Performance von Exceptions siehe auch: try/catch

Sarkusmus ist, wenn nichts mehr hilft, außer Lachen.

1.274 Beiträge seit 2005
vor 17 Jahren

Danke für deine Mühe diesen Artikel zu schreiben. Mir läuft es jedesmal schauderhaft über den Rücken wenn ich Beispiele sehe die beim Datenbankzugriff kein Using verwenden. Buaaa.

Auch der Link von Lord Hessia ist sehr interessant, ich hab auch immer geglaubt das Execeptions fürchterlich lange sind.

"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein

1.433 Beiträge seit 2006
vor 17 Jahren

Gratulation zum Artikel. Wirklich kurz und gut sowie leicht verständlich.

Grüsse
Daniel
Space Profile
Wer nicht fragt, der nicht gewinnt

.Kai Themenstarter:in
1.130 Beiträge seit 2005
vor 17 Jahren

Ich habe mal den Diskussionteil abgetrennt, bitte im Thread Datenbanken richtig öffnen und schließen fortsetzen.

F
10.010 Beiträge seit 2004
vor 17 Jahren

Eine kleine Verbesserung des Textes:

Du schreibst, das Du per "Scope" den Quelltext übersichtlicher und ausserdem
die Verbindung schliesst.
Das ist Falsch.

In deinem Beispiel benutzt Du "Using" und das ist der Grund für das schliessen.
Using ist eine Abkürzung für folgende Schreibweise:


ODBCConnection con = new ODBCConnection(...);
try
{
....
}
finally
{
  con.Dispose();
}

Using macht in einem Finally Block immer ein Dispose, weshalb die Klasse
die Instantiiert werden soll IDisposable implementieren muss.

.Kai Themenstarter:in
1.130 Beiträge seit 2005
vor 17 Jahren

Original von FZelle
Eine kleine Verbesserung des Textes:

Du schreibst, das Du per "Scope" den Quelltext übersichtlicher und ausserdem
die Verbindung schliesst.
Das ist Falsch.

In deinem Beispiel benutzt Du "Using" und das ist der Grund für das schliessen.
Using ist eine Abkürzung für folgende Schreibweise:

  
ODBCConnection con = new ODBCConnection(...);  
try  
{  
....  
}  
finally  
{  
  con.Dispose();  
}  
  

Using macht in einem Finally Block immer ein Dispose, weshalb die Klasse
die Instantiiert werden soll IDisposable implementieren muss.

Korrekt! Ist im Text nicht genau genug formuliert.

Das using im IL in ein Try-Catch Konstrukt übersetzt wird, hatte ich allerdings geschrieben.
Ich überarbeite den Artikel bei Gelegenheit und korrigiere die entsprechenden Stellen.

Vielen Dank für den Hinweis.

347 Beiträge seit 2006
vor 17 Jahren

Original von .Kai
Korrekt! Ist im Text nicht genau genug formuliert.

Das using im IL in ein Try-Catch Konstrukt übersetzt wird, hatte ich allerdings geschrieben.
Ich überarbeite den Artikel bei Gelegenheit und korrigiere die entsprechenden Stellen. Hat nichts mit "genau genug formuliert" zu tun.
Es ist der "finally"-block, der zählt, nicht "Catch".
Außerdem sollte das hier:

using (OdbcConnection sqlConn = new OdbcConnection()
{
  OdbcCommand sqlCmd = new OdbcCommand(sql, sqlConn);
  sqlConn.Open();
  OdbcDataReader sqlReader = sqlCmd.ExecuteReader();
  while (sqlReader.Read())
  {
    Console.WriteLine(sqlReader["ID"]);
  }
  sqlReader.Close();
  sqlConn.Close();
}

So aussehen:

using (OdbcConnection sqlConn = new OdbcConnection())
using (OdbcCommand sqlCmd = sqlConn.CreateCommand())
{
  sqlCmd.CommandText = sql;
  sqlConn.Open();
  using(OdbcDataReader sqlReader = sqlCmd.ExecuteReader())
  {
    while (sqlReader.Read())
    {
      Console.WriteLine(sqlReader["ID"]);
    }
  }
}

Auf die Art verhinderst du, dass nervige Finalizer ausgeführt werden.
Connection.Close in einem using-Block aufzurufen macht auch keinen Sinn, das erledigt Dispose schon.
Und den Indexer eines DataReaders sollte man IMHO auch nicht wirklich benutzen, sondern die typisierten Methoden, die den Wert mit dem richtigen Typ aus dem DB cursor ziehen.

Mit Hilfe dieser kleinen Änderung am Code kann man nun davon ausgehen, daß die Verbindung zur Datenbank immer geschlossen wird. Die Verbindung wird immer geschlossen. Das erledigt der Finalizer der Connection. Man benutzt using nicht um zu verhindern dass die Verbindung offen bleibt, sondern um zu verhindern dass Finalizer ausgeführt werden und damit man weiß wann die Verbindung geschlossen wird. 😉