Was ist der richtige Weg, um eine SQL-Verbindung, um sicherzustellen, wird geschlossen, wenn eine Ausnahme ausgelöst wird?

StackOverflow https://stackoverflow.com/questions/141204

  •  02-07-2019
  •  | 
  •  

Frage

Ich verwende ein Muster, das oft so etwas wie dies aussieht. Ich frage mich, ob dies in Ordnung ist, oder wenn es eine bewährte Methode, die ich hier nicht beantrage.

Insbesondere frage ich mich; in dem Fall, dass eine Ausnahme ausgelöst wird, ist der Code, den ich in der schließlich blockieren genug, um sicherzustellen haben, dass die Verbindung in geeigneter Weise geschlossen ist?

public class SomeDataClass : IDisposable
{
    private SqlConnection _conn;

    //constructors and methods

    private DoSomethingWithTheSqlConnection()
    {
        //some code excluded for brevity

        try
        {
            using (SqlCommand cmd = new SqlCommand(SqlQuery.CountSomething, _SqlConnection))
            {
                _SqlConnection.Open();
                countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
            }
        }
        finally
        {
            //is this the best way?
            if (_SqlConnection.State == ConnectionState.Closed)
                _SqlConnection.Close();
        }

        //some code excluded for brevity
    }

    public Dispose()
    {
        _conn.Dispose();
    }
}
War es hilfreich?

Lösung

Wickeln Sie Ihren Datenbank-Handling-Code in einem "mit"

using (SqlConnection conn = new SqlConnection (...))
{
    // Whatever happens in here, the connection is 
    // disposed of (closed) at the end.
}

Andere Tipps

Das .Net Framework mantains einen Verbindungspool für einen Grund. Vertraue! :) Sie müssen nicht nur so viel Code schreiben, um die Datenbank und lassen Sie die Verbindung zu verbinden.

Sie können mit nur die ‚Verwendung‘ Aussage und seien Sie versichert, dass ‚IDBConnection.Release ()‘ wird die Verbindung für Sie schließen.

Sehr aufwendige ‚Lösungen‘ sind in der Regel in fehlerhaftem Code führen. Einfach ist besser.

MSDN Docs diese machen ziemlich klar ...

  • Die Close-Methode rollt alle ausstehenden Transaktionen zurück. Es gibt dann die Verbindung an den Verbindungspool, oder schließt die Verbindung, wenn Verbindungspooling deaktiviert ist.

Sie haben wahrscheinlich nicht (und wollen nicht) Verbindungspooling deaktivieren, so dass der Pool verwaltet schließlich den Zustand der Verbindung, nachdem Sie auf „Schließen“ nennen. Dies könnte wichtig sein, wie man es von der Datenbank Server-Seite an allen offenen Verbindungen suchen kann verwechselt werden.


  • Eine Anwendung kann Schließen mehr als einmal aufrufen. Keine Ausnahme erzeugt.

Warum also die Mühe Tests für Closed? Rufen Sie Close ().


  • Schließen und Entsorgen sind funktionell gleichwertig.

Aus diesem Grunde ist ein mit Block führt zu einer geschlossenen Verbindung. mit ruft Dispose für Sie.


  • Rufen Sie nicht schließen oder Entsorgen auf einer Verbindung, einem Datareader oder ein anderes verwaltetes Objekt in der Finalize-Methode der Klasse.

Wichtige Sicherheitsspitze. Danke, Egon.

Ich vermute, dass durch "_SqlConnection.State == ConnectionState.Closed" Sie gemeint! =.

Dies wird sicherlich funktionieren. Ich denke, es üblich ist, die Verbindung enthalten sich in einem mit Statement-Objekt, aber was Sie haben, ist gut, wenn man das gleiche Verbindungsobjekt aus irgendeinem Grunde wieder verwenden will.

Eine Sache, die Sie auf jeden Fall ändern sollen, ist jedoch die Methode Dispose (). Sie sollten das Verbindungsobjekt in dispose nicht verweisen, weil sie zu diesem Zeitpunkt bereits abgeschlossen hat. Sie sollten stattdessen die empfohlene Entsorgen Muster folgen.

Da Sie IDisposables sowieso verwenden. Sie können das ‚mit‘ Schlüsselwort verwenden, die im Wesentlichen äquivalent ist, in einem finally-Block verfügen nennen, aber es sieht besser aus.

Sehen Sie diese Frage für die Antwort ein:

Schließen und Entsorgen - welche nennen

Wenn Ihre Verbindung Lebensdauer ein einzelner Methodenaufruf ist, verwenden Sie das using Merkmal der Sprache das richtige clean-up der Verbindung zu gewährleisten. Während ein try/finally Block funktionell gleich ist, erfordert es mehr Code und IMO weniger lesbar. Es besteht keine Notwendigkeit, den Status der Verbindung zu überprüfen, können Sie unabhängig nennen Dispose und es wird übernimmt die Verbindung Reinigung-up.

Wenn Ihre Verbindung Lebensdauer der Lebensdauer eines enthaltenden Klasse entspricht, dann implementieren IDisposable und clean-up die Verbindung in Dispose.

Setzen Sie die Verbindung schließen Code in einem „Finally“ Block wie es Ihnen zeigen. Schließlich werden die Blöcke ausgeführt, bevor die Ausnahme ausgelöst wird. Mit einer „mit“ Block funktioniert genauso gut, aber ich finde die explizite „Finally“ Methode klarer.

Mit Aussagen sind ein alter Hut für viele Entwickler, aber jüngere Entwickler vielleicht nicht wissen, dass aus der Hand.

keine Notwendigkeit für eine try..finally um eine "Verwendung", die mit ein try..finally

Darf ich vorschlagen, diese:


    class SqlOpener : IDisposable
    {
        SqlConnection _connection;

        public SqlOpener(SqlConnection connection)
        {
            _connection = connection;
            _connection.Open();

        }

        void IDisposable.Dispose()
        {
            _connection.Close();
        }
    }

    public class SomeDataClass : IDisposable
    {
        private SqlConnection _conn;

        //constructors and methods

        private void DoSomethingWithTheSqlConnection()
        {
            //some code excluded for brevity
            using (SqlCommand cmd = new SqlCommand("some sql query", _conn))
            using(new SqlOpener(_conn))
            {
                int countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
            }
            //some code excluded for brevity
        }

        public void Dispose()
        {
            _conn.Dispose();
        }
    }

Ich hoffe, das hilft:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top