Meilleures pratiques concernant le partage d'IDbConnection ou d'une chaîne / fabrique de connexion dans votre code .Net

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

Question

Je me demande quelle serait la meilleure méthode pour maintenir les connexions à la base de données dans une application .Net (ADO.NET, mais je suppose que la pratique devrait être la même pour toutes les couches de données). Devrais-je créer une connexion à une base de données et la propager dans toute mon application, ou serait-il préférable de simplement passer des chaînes de connexion / des fabriques et de créer une connexion ad-hoc, le cas échéant.

Si je comprends bien, la performance n’est pas significative en pooling, cela me permet de récupérer assez facilement de connexions rompues (une nouvelle connexion sera créée), mais un objet de connexion est une belle abstraction et un niveau de création relativement élevé. une nouvelle connexion pour chaque opération (pas une commande SQL mais une opération d’application) génère du code supplémentaire dupliqué et donne l’impression d’une perte de temps / ressources (?).

Que pensez-vous de ces 2 cas, quels sont leurs inconvénients / avantages et quelle approche utilisez-vous dans vos applications réelles?

Merci

Était-ce utile?

La solution

Je me suis retrouvé dans l'obligation de faire passer un objet de connexion afin de permettre à plusieurs objets métier de se sauvegarder dans la base de données au sein d'une seule transaction.

Si chaque objet métier devait créer son propre SQLConnection dans la base de données, la transaction deviendrait une transaction distribuée et je voulais éviter cela.

Je n'aimais pas devoir passer l'objet SQLConnection en tant que paramètre pour enregistrer un objet. J'ai donc créé un ConnectionManager qui gère la création de l'objet SQLConnection pour moi, en suivant l'utilisation de l'objet SQLConnection et en déconnectant l'objet SQLConnection lorsqu'il ne l'est pas. en cours d'utilisation.

Voici un exemple de code de 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

}

Voici comment je l'utiliserais à partir d'un objet métier:

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.
    }
}

J'enregistre un objet métier et tous ses enfants sont également enregistrés à l'aide du même objet de connexion. Lorsque l'étendue se détache du parent d'origine, l'instruction using ferme la connexion.

C’est un schéma que j’ai appris de Rocky Lhotka dans son cadre d’application de la CSLA.

Keith

Autres conseils

Vous ne devriez vraiment pas gérer ce problème vous-même, car il existe d'innombrables outils qui peuvent le faire pour vous.

Si vous voulez vraiment le faire vous-même, consultez le modèle d'Unité de Travail . où vous pouvez gérer le cycle de vie de la connexion / transaction. Vous ne voulez certainement pas essayer de naviguer dans les eaux troubles où des connexions sont ouvertes / fermées à différents endroits.

Si vous décidez de laisser vos composants ouvrir directement les connexions à la base de données, il est probable que le cycle de vie de la connexion sera trop détaillé et qu'il en résulte de nombreuses connexions ouvertes / fermées pour une opération utilisateur unique.

Le fournisseur ADO.NET SQL Server effectue la mise en pool de la connexion elle-même. Vous pouvez contrôler la taille du pool à l'aide de MinPoolSize et MaxPoolSize dans la chaîne de connexion.

Une chose à laquelle il faut se méfier dans votre exemple est que les applications ASP.NET ne doivent pas utiliser le stockage ThreadStatic, car un thread peut être réutilisé. Si vous ne nettoyez pas tous vos objets, vous vous retrouvez avec une connexion suspendue. autour.

Dans une application ASP.NET, j'utiliserais plutôt la collection HttpContext.Items. Vous implémentez IDisposable, mais j'ai déjà vu des scénarios dans lesquels les développeurs oublient d'appeler Dispose ou placent le code dans un bloc using.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top