Pregunta

Me aparentemente tiene dos opciones:

  1. Haz de mi clase implemente IDisposable. Crear mis casos DbCommand como campos private readonly, y en el constructor, agregar los parámetros que utilizan. Siempre que quiero escribir en la base de datos, se unen a estos parámetros (reutilización de las mismas instancias de comando), establecer las propiedades Connection y Transaction, entonces llaman ExecuteNonQuery. En el método Dispose, llame Dispose en cada uno de estos campos.
  2. Cada vez que quiero escribir en la base de datos, escribir using(var cmd = new DbCommand("...", connection, transaction)) alrededor del uso del comando, y añadir parámetros y se unen a ellos cada vez, así, antes de llamar a ExecuteNonQuery. Asumo que no necesito un nuevo comando para cada consulta, sólo un nuevo comando para cada vez que abra la base de datos (¿verdad?).

Ambos parecen poco elegante y posiblemente incorrecta.

Para # 1, es molesto para mis usuarios que esta clase es ahora IDisposable sólo porque he utilizado unos DbCommands (que debe ser un detalle de implementación que no se preocupan). También estoy un poco sospechoso que el mantenimiento de una instancia DbCommand alrededor podría bloquear inadvertidamente la base de datos o algo?

Para # 2, se siente como que estoy haciendo un montón de trabajo (en términos de objetos .NET) cada vez que quiero escribir en la base de datos, sobre todo con el parámetro añadido. Parece que creo el mismo objeto cada vez, que sólo se siente como una mala práctica.

Para referencia, aquí es mi código actual, usando # 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
}
¿Fue útil?

Solución

Domenic, Disponer un SQLiteCommand simplemente señala su lector activo de disponer que es lector y establece los parámetros y referencia de conexión a null.

Usted no está en riesgo de fuga de recursos cambiando el comando todo el tiempo que disponer adecuadamente del lector ejecutado y cerrado / disponer de la conexión.

Por lo tanto, la reutilización de un comando en caché y simplemente asignar valores a los parámetros es, con mucho, la implementación más eficiente.

.Prepare () es una noop en SQLiteCommand lo que no hay beneficio que se tenía allí.

Otros consejos

No hay una sola manera "correcta" para manejar su ciclo de objeto de base de la vida. Es todo depende de sus necesidades de aplicación.

Mi preferencia personal es mantener el código tan simple como sea posible. Tiendo recrear objetos de comando y los parámetros según sea necesario. De este modo, mis funciones sean tan independientes como sea posible. Se ha simplificado enormemente cualquier factorización re que he tenido que hacer.

Si usted está preocupado por el impacto en el rendimiento de los objetos que recrean usted debe cargar un generador de perfiles y ver dónde están sus cuellos de botella son. En las aplicaciones que he construido, he encontrado el tiempo dedicado a la creación de objetos DbCommand es tan insignificante en comparación con el tiempo de ejecutar la consulta que en realidad no factor en el rendimiento de mi aplicaciones.

he encontrado con sqlserver si reutilizamos el comando con misma conexión, es mucho más rápido. Mi plan para poner a prueba para diferentes conexiones y transacciones pero parecen ser más rápido.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top