Question

J'ai apparemment deux choix:

  1. Faites ma classe IDisposable mettre en œuvre. Créer mes instances DbCommand comme des champs de private readonly, et dans le constructeur, ajouter les paramètres qu'ils utilisent. Chaque fois que je veux écrire à la base de données, se lier à ces paramètres (réutilisant les mêmes instances de commande), définissez les propriétés de Connection et Transaction, puis appelez ExecuteNonQuery. Dans la méthode Dispose, appelez Dispose sur chacun de ces champs.
  2. Chaque fois que je veux écrire à la base de données, écrivez using(var cmd = new DbCommand("...", connection, transaction)) autour de l'utilisation de la commande, et ajouter des paramètres et se lient à eux chaque fois ainsi, avant d'appeler ExecuteNonQuery. Je suppose que je ne suis pas besoin d'une nouvelle commande pour chaque requête, juste une nouvelle commande pour chaque fois que j'ouvre la base de données (à droite?).

Ces deux semblent un peu inélégante et peut-être incorrect.

Pour # 1, il est gênant pour mes utilisateurs que je cette classe est maintenant IDisposable juste parce que je l'ai utilisé quelques DbCommands (qui devrait être un détail de mise en œuvre qu'ils ne se soucient pas). Je suis aussi un peu suspecte que le maintien d'une instance de DbCommand autour peut verrouiller la base de données par inadvertance ou quelque chose?

Pour # 2, on dirait que je fais beaucoup de travail (en termes d'objets .NET) chaque fois que je veux écrire à la base de données, en particulier avec le paramètre ajoutée. Il semble que je crée le même objet à chaque fois, ce qui se sent comme une mauvaise pratique.

Pour référence, voici mon code actuel, en utilisant # 1:

using System;
using System.Net;
using System.Data.SQLite;

public class Class1 : IDisposable
{
    private readonly SQLiteCommand updateCookie = new SQLiteCommand("UPDATE moz_cookies SET value = @value, expiry = @expiry, isSecure = @isSecure, isHttpOnly = @isHttpOnly WHERE name = @name AND host = @host AND path = @path");
    public Class1()
    {
        this.updateCookie.Parameters.AddRange(new[]
                            {
                                new SQLiteParameter("@name"),
                                new SQLiteParameter("@value"),
                                new SQLiteParameter("@host"),
                                new SQLiteParameter("@path"),
                                new SQLiteParameter("@expiry"),
                                new SQLiteParameter("@isSecure"),
                                new SQLiteParameter("@isHttpOnly")
                            });
    }

    private static void BindDbCommandToMozillaCookie(DbCommand command, Cookie cookie)
    {
        long expiresSeconds = (long)cookie.Expires.TotalSeconds;

        command.Parameters["@name"].Value = cookie.Name;
        command.Parameters["@value"].Value = cookie.Value;
        command.Parameters["@host"].Value = cookie.Domain;
        command.Parameters["@path"].Value = cookie.Path;
        command.Parameters["@expiry"].Value = expiresSeconds;
        command.Parameters["@isSecure"].Value = cookie.Secure;
        command.Parameters["@isHttpOnly"].Value = cookie.HttpOnly;
    }

    public void WriteCurrentCookiesToMozillaBasedBrowserSqlite(string databaseFilename)
    {
        using (SQLiteConnection connection = new SQLiteConnection("Data Source=" + databaseFilename))
        {
            connection.Open();
            using (SQLiteTransaction transaction = connection.BeginTransaction())
            {
                this.updateCookie.Connection = connection;
                this.updateCookie.Transaction = transaction;

                foreach (Cookie cookie in SomeOtherClass.GetCookieArray())
                {
                    Class1.BindDbCommandToMozillaCookie(this.updateCookie, cookie);
                    this.updateCookie.ExecuteNonQuery();
                }

                transaction.Commit();
            }
        }
    }

    #region IDisposable implementation
    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed && disposing)
        {
            this.updateCookie.Dispose();
        }
        this.disposed = true;
    }
    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }
    ~Class1()
    {
        this.Dispose(false);
    }

    private bool disposed;
    #endregion
}
Était-ce utile?

La solution

Domenic, La disposition d'un SQLiteCommand signale simplement son lecteur actif pour disposer son lecteur et établit les paramètres de connexion et de référence à null.

Vous n'êtes pas à risque de fuite de ressource en mettant en cache une commande aussi longtemps que vous éliminer de manière appropriée du lecteur exécuté et proche / Éliminez de la connexion.

Ainsi, la réutilisation d'une commande en cache et en attribuant simplement des valeurs aux paramètres est de loin la mise en œuvre la plus efficace.

.Prepare () est un noop en SQLiteCommand donc il n'y a aucun avantage à être pris sur place.

Autres conseils

Il n'y a pas simple « droit chemin » pour gérer le cycle de vie de l'objet de base de données. Il est tout dépend de vos besoins d'application.

Ma préférence personnelle est de garder le code aussi simple que possible. J'ai tendance à recréer des objets de commande et paramètres au besoin. Cela permet à mes fonctions être aussi autonome que possible. Il a grandement simplifié toute l'affacturage re que j'ai dû le faire.

Si vous êtes préoccupé par l'impact sur les performances des objets recréant vous devez charger un profileur et voir où votre cou de bouteille sont. Dans les applications que j'ai construit, j'ai trouvé le temps passé à la création d'objets DbCommand est tellement sans conséquence par rapport au temps passé à exécuter la requête qu'il ne tient pas vraiment à mes performances des applications.

Je l'ai trouvé avec SQLServer si nous réutilisons la commande avec la même connexion, son beaucoup plus rapide. Je prévois de tester les connexions et les transactions différentes, mais ils semblent être plus rapide.

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