Frage

Ich habe scheinbar zwei Möglichkeiten:

  1. Machen Sie meine Klasse IDisposable implementieren. Erstellen Sie meine DbCommand Instanzen als private readonly Feldern und in den Konstruktor, fügen Sie die Parameter, die sie verwenden. Jedes Mal, wenn ich in die Datenbank schreiben wollen, binden an diese Parameter (die gleichen Befehlsinstanzen Wiederverwendung), stellen Sie die Connection und Transaction Eigenschaften, dann ExecuteNonQuery nennen. Im Dispose Methode, rufen Dispose auf jedem dieser Felder aus.
  2. Jedes Mal, wenn ich in die Datenbank schreiben wollen, using(var cmd = new DbCommand("...", connection, transaction)) um die Verwendung des Befehls schreiben und Parameter hinzufügen und jedes Mal, als auch an sie binden, bevor ExecuteNonQuery aufrufen. Ich nehme an, ich keinen neuen Befehl für jede Abfrage benötigen, nur einen neuen Befehl für jedes Mal, wenn ich die Datenbank öffnen (rechts?).

Beide scheinen etwas unelegant und möglicherweise falsch.

# 1 ist es ärgerlich für meine Nutzer, dass ich diese Klasse jetzt gerade ist IDisposable weil ich ein paar DbCommands verwendet haben (die eine Implementierung Detail sein sollte, dass sie etwa nicht egal). Ich bin auch ein wenig verdächtig, dass eine DbCommand Instanz zu halten um versehentlich die Datenbank oder etwas könnte sperren?

# 2, fühlt es sich wie ich eine Menge Arbeit zu tun (in Bezug auf .NET-Objekte) jedes Mal, wenn ich in die Datenbank schreiben wollen, vor allem mit dem Parameter-Zugabe. Es scheint, wie ich das gleiche Objekt jedes Mal zu erstellen, die genau wie schlechte Praxis anfühlt.

Als Referenz hier ist mein aktueller Code, mit # 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
}
War es hilfreich?

Lösung

Domenic, einfach signalisiert seine aktive Leser einen SQLiteCommand Entsorgung zu entsorgen Leser es und legt die Parameter und Verbindungsreferenz auf null.

Sie sind nicht das Risiko der Ressourcen-Lecks durch einen Befehl Cachen, solange Sie den ausgeführten Lesers und schließen / Entsorgen Sie die Verbindung ordnungsgemäß entsorgen.

Also, eine zwischengespeicherte Befehl Wiederverwendung und einfach Werte für die Parameter Zuordnung ist bei weitem die effizienteste Implementierung.

.Prepare () ist eine noop in SQLiteCommand so gibt es keinen Vorteil gibt zu haben ist.

Andere Tipps

Es gibt keinen einzigen „richtigen Weg“, um Ihren Datenbankobjekt Lebenszyklus zu verarbeiten. Es ist alles abhängig von den Anforderungen Ihrer Anwendung.

Meine persönliche Präferenz ist, den Code so einfach wie möglich zu halten. Ich neige dazu, Befehl und Parameter-Objekte zu erstellen, wie gebraucht. Auf diese Weise kann meine Funktionen als selbst wie möglich enthalten sein. Es hat sich stark jede Re-Factoring vereinfacht ich habe musste.

Wenn Sie besorgt über die Performance-Einbußen der Neuen Objekte, die Sie einen Profiler laden sollten und sehen, wo Sie Ihre Flaschenhälse sind. In Anwendungen, habe ich gebaut habe ich die Zeit damit verbracht zu schaffen DbCommand Objekte gefunden, so belanglos ist im Vergleich zu der Zeit damit verbracht die Ausführung die Abfrage, die es Faktor nicht wirklich in meiner apps Leistung.

Ich habe mit Sqlserver gefunden, wenn wir den Befehl mit derselben Verbindung, seine viel schneller wieder verwenden. Ich plane für verschiedene Verbindungen und Transaktionen zu testen, aber sie scheinen schneller zu sein.

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