Domanda

I apparentemente ho due scelte:

  1. Fai la mia classe di implementare IDisposable. Creare le mie istanze DbCommand come campi private readonly, e nel costruttore, aggiungere i parametri che usano. Ogni volta che voglio scrivere al database, legarsi a questi parametri (riutilizzando le stesse istanze di comando), impostare le proprietà Connection e Transaction, quindi chiamare ExecuteNonQuery. Nel metodo Dispose, chiamare Dispose su ciascuno di questi campi.
  2. Ogni volta che voglio scrivere nel database, scrivere using(var cmd = new DbCommand("...", connection, transaction)) intorno l'utilizzo del comando, e aggiungere i parametri e si legano a loro ogni volta, così, prima di chiamare ExecuteNonQuery. Suppongo non ho bisogno di un nuovo comando per ogni query, solo un nuovo comando per ogni volta che apro il database (giusto?).

Entrambi questi sembrano un po 'poco elegante ed eventualmente corretto.

Per 1 #, è fastidioso per i miei utenti che questa classe è ora IDisposable solo perché ho usato un paio di DbCommands (che dovrebbe essere un dettaglio di implementazione che non si preoccupano). Anch'io sono un po 'sospetto che mantenere un'istanza DbCommand intorno potrebbe inavvertitamente bloccare il database o qualcosa del genere?

Per 2 #, ci si sente come sto facendo un sacco di lavoro (in termini di oggetti .NET) ogni volta che voglio scrivere nel database, in particolare con il parametro aggiunto. Sembra che creo lo stesso oggetto ogni volta che si sente proprio come una cattiva pratica.

Per avere un riferimento, ecco il mio codice corrente, utilizzando # 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
}
È stato utile?

Soluzione

Domenic, Disporre uno SQLiteCommand segnala semplicemente il suo lettore attivo smaltire è lettore e imposta i parametri e riferimento collegamento a null.

Non siete a rischio di perdita di risorse per la memorizzazione nella cache di un comando fino a quando si smaltire correttamente il lettore eseguito e vicino / Smaltire della connessione.

Quindi, il riutilizzo di un comando di cache e semplicemente assegnando valori ai parametri è di gran lunga la più efficace attuazione.

.Prepare () è una noop in SQLiteCommand quindi non c'è alcun beneficio per essere avuto là.

Altri suggerimenti

Non c'è alcun singolo "modo giusto" per gestire il ciclo di database ad oggetti di vita. E 'tutto dipende da vostre esigenze applicative.

La mia preferenza personale è quello di mantenere il codice più semplice possibile. Io tendo a ricreare oggetti Command e Parameter, se necessario. In questo modo le mie funzioni essere il più autonomo possibile. Esso ha notevolmente semplificato qualsiasi factoring re che ho dovuto fare.

Se siete preoccupati per il calo di prestazioni degli oggetti che ricreano si dovrebbe caricare un profiler e vedere dove i vostri colli di bottiglia sono. Nelle applicazioni Ho costruito, ho trovato il tempo speso la creazione di oggetti DbCommand è così irrilevante rispetto al tempo trascorso esecuzione della query che in realtà non fattore per la mia prestazione applicazioni.

che ho trovato con SQLServer se riutilizziamo il comando con stessa connessione, la sua molto più veloce. Ho intenzione di provare per diverse connessioni e transazioni, ma sembrano essere più veloce.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top