Best Practices wieder teilen IDbConnection oder Verbindungszeichenfolge / Fabrik in Ihrem .NET-Code

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

Frage

Ich frage mich, was die beste prectice bezüglich mainataining Verbindungen zur Datenbank in Net-Anwendung sei (ADO.NET aber ich denke, die Praxis sollte für jede Datenschicht sein). Sollte ich eine Datenbankverbindung erstellen und verbreiten sie während meiner Anwendung, oder wäre es besser, nur Verbindungszeichenfolgen / Fabriken passieren und eine Verbindung ad-hoc erstellen, wenn es benötigt wird.

Wie ich verstehe perfomance Hit bei Pooling nicht signifcant ist und es erlaubt mich von unterbrochenen Verbindungen zu erholen ganz einfach (nur eine neue Verbindung erstellt wird), aber dann wieder ein Verbindungsobjekt ist eine schöne, relativ hohe Abstraktionsebene und die Schaffung von eine neue Verbindung für jeden Betrieb (nicht SQL-Befehl, sondern Anwendungsbetrieb) erzeugt zusätzliche, dupliziert Code und fühlt sich wie eine Verschwendung von Zeit / Ressourcen (?).

Was Sie über diese 2 Fälle denken, was sind ihre Nachteile / Vor- und welcher Ansatz verwenden Sie in Ihren realen Anwendungen?

Danke

War es hilfreich?

Lösung

Ich fand mich um eine Verbindung Objekt zu übergeben, um so ich Objekte mehr Unternehmen ermöglichen könnte, mich in die Datenbank in einer einzigen Transaktion zu speichern.

Wenn jedes Business-Objekt hatte seine eigene SQLConnection in der Datenbank zu erstellen, würde die Transaktion zu einer verteilten Transaktion eskalieren und das wollte ich vermeiden.

Ich habe nicht wie das SQLConnection-Objekt als Parameter zu übergeben, die ein Objekt zu speichern, so habe ich einen Connectionmanager, den das SQLConnection-Objekt für mich Griffe zu schaffen, die Verwendung der SQLConnection Objektverfolgung, und Trennen des SQLConnection-Objekts, wenn nicht in Gebrauch ist.

Hier ist ein Code als ein Beispiel für die Connectionmanager:

public class ConnectionManager: IDisposable
{
    private ConnectionManager instance;

    [ThreadStatic]
    private static object lockObject; 
    private static Object LockObject
    {
        get
        {
            if (lockObject == null)
                lockObject = new object();
            return lockObject;
        }
    }

    [ThreadStatic]
    private static Dictionary<string, ConnectionManager> managers;
    private static Dictionary<string, ConnectionManager> Managers
    {
        get
        {
            if (managers == null)
                managers = new Dictionary<string, ConnectionManager>();
            return managers;
        }
    }

    private SqlConnection connection = null;
    private int referenceCount;
    private string name;


    public static ConnectionManager GetManager(string connectionName)
    {
        lock (LockObject)
        {
            ConnectionManager mgr;
            if (Managers.ContainsKey(connectionName))
            {
                mgr = Managers[connectionName];
            }
            else
            {
                mgr = new ConnectionManager(connectionName);
                Managers.Add(connectionName, mgr);
            }

            mgr.AddRef();
            return mgr;
        }
    }

    private ConnectionManager(string connectionName)
    {
        name = connectionName;
        connection = new SqlConnection(GetConnectionString(connectionName));
        connection.Open();
    }

    private string GetConnectionString(string connectionName)
    {
        string conString = Configuration.ConnectionString;
        return conString; 
    }

    public SqlConnection Connection
    {
        get { return connection; }
    }

    private void AddRef()
    {
        referenceCount += 1;
    }

    private void DeRef()
    {
        lock (LockObject)
        {
            referenceCount -= 1;
            if (referenceCount == 0)
            {
                connection.Dispose();
                Managers.Remove(name);
            }
        }
    }

#region IDisposable Members

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            DeRef();
        }
    }

    ~ConnectionManager()
    {
        Dispose(false);
    }

#endregion

}

Hier ist, wie ich es von einem Business-Objekt verwenden würde:

public void Save()
{   
    using (ConnectionManager mrg = ConnectionManager.GetManager("SQLConnectionString")
    {
        using (SQLCommand cmd = new SQLCommand)
        {
            cmd.connection = mgr.Connection
            // More ADO Code Here
        }

        _childObject.Save(); //this child object follows the same pattern with a using ConnectionManager.
    }
}

ich spare ein Business-Objekt und alle seine Kinder werden auch mit dem gleichen Verbindungsobjekt gespeichert. Wenn der Umfang von der ursprünglichen Mutter fällt weg, die using-Anweisung schließt die Verbindung.

Dies ist ein Muster, das ich von Rocky Lhotka in seinem CSLA Rahmen gelernt.

Keith

Andere Tipps

Sie sollten wirklich nicht das Problem selbst werden um, da es unzählige Werkzeuge gibt, die es für Sie tun können.

Wenn Sie wirklich es selbst tun wollen, dann schauen Sie in den Unit of Work Muster wo Sie Verbindung / Transaktionslebenszyklus verwalten. Sie wollen sicher nicht versuchen, die chaotisch Gewässer zu navigieren, wo es Verbindungen an verschiedenen Orten geöffnet / geschlossen werden.

Wenn Sie sich entscheiden, Ihre Komponenten lassen sich direkt öffnen db Verbindungen dann ist es wahrscheinlich, dass die Verbindung Lebenszyklus zu feinkörnig sein und in vielen offen / geschlossen Verbindungen für einen einzelnen Benutzer Betrieb zur Folge haben.

ADO.NET SQL Server-Anbieter hat die Verbindung Pooling selbst. Sie können die Poolgröße von MinPoolSize und MaxPoolSize in der Verbindungszeichenfolge steuern.

Eine Sache von in Ihrem Beispiel, vorsichtig zu sein, ist, dass ASP.NET-Anwendungen nicht Threadstatic Speicher verwenden sollten, da ein Thread kann wieder verwendet wird, und wenn Sie alle Ihre Objekte nicht bereinigen Sie mit einer Verbindung hängenden Ende um.

In einem ASP.NET-app würde ich stattdessen die HttpContext.Items Sammlung verwenden. Sie implementieren IDisposable, aber ich habe gesehen, wo Szenarien Devs vergessen Entsorgen anrufen oder den Code in einem mit Block.

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