Pregunta

Se preguntaba si se recomienda pasar un objeto de conexión de base de datos (a otros módulos) o dejar que el método (en el otro módulo) se encargue de configurarlo. Me inclino por dejar que el método lo configure para no tener que verificar el estado de la conexión antes de usarlo, y que la persona que llama transmita los datos necesarios al método de llamada que se necesitaría para configurar la conexión.

¿Fue útil?

Solución

Personalmente, me gusta usar conexiones de amplio alcance; ábralos tarde, utilícelos y ciérrelos (en un bloque " utilizando " todo dentro del método local). La agrupación de conexiones se ocupará de reutilizar la conexión en la mayoría de los casos, por lo que no hay una sobrecarga real en este enfoque.

La principal ventaja de pasar conexiones se usó para que puedas pasar la transacción; sin embargo, TransactionScope es una forma más sencilla de compartir una transacción entre métodos .

Dado que las clases son específicas de la implementación, escribiría cada una para abrir su propia transacción nativa. De lo contrario, puede usar los métodos de fábrica de ado.net para crear el tipo apropiado a partir del archivo de configuración (el nombre del proveedor).

Otros consejos

Personalmente, me gusta almacenar una pila de mi conexión abierta actual y las transacciones encima de Thread Local Storage usando SetData y GetData. Defino una clase que administra mis conexiones a la base de datos y le permito usar el patrón de disposición. Esto me ahorra la necesidad de pasar conexiones y transacciones, que es algo que creo que confunde y complica el código.

Recomiendo encarecidamente a en contra de dejar los métodos para abrir conexiones cada vez que necesiten datos. Esto conducirá a una situación realmente mala en la que es difícil administrar las transacciones en toda la aplicación y se abren y cierran demasiadas conexiones (sé acerca de la agrupación de conexiones, aún es más costoso buscar una conexión de la agrupación de lo que es. para reutilizar un objeto)

Así que termino teniendo algo en este sentido (totalmente sin probar):

class DatabaseContext : IDisposable {

    List<DatabaseContext> currentContexts;
    SqlConnection connection;
    bool first = false; 

    DatabaseContext (List<DatabaseContext> contexts)
    {
        currentContexts = contexts;
        if (contexts.Count == 0)
        {
            connection = new SqlConnection(); // fill in info 
            connection.Open();
            first = true;
        }
        else
        {
            connection = contexts.First().connection;
        }

        contexts.Add(this);
    }

   static List<DatabaseContext> DatabaseContexts {
        get
        {
            var contexts = CallContext.GetData("contexts") as List<DatabaseContext>;
            if (contexts == null)
            {
                contexts = new List<DatabaseContext>();
                CallContext.SetData("contexts", contexts);
            }
            return contexts;
        }
    }

    public static DatabaseContext GetOpenConnection() 
    {
        return new DatabaseContext(DatabaseContexts);
    }


    public SqlCommand CreateCommand(string sql)
    {
        var cmd = new SqlCommand(sql);
        cmd.Connection = connection;
        return cmd;
    }

    public void Dispose()
    {
        if (first)
        {
            connection.Close();
        }
        currentContexts.Remove(this);
    }
}



void Test()
{
    // connection is opened here
    using (var ctx = DatabaseContext.GetOpenConnection())
    {
        using (var cmd = ctx.CreateCommand("select 1"))
        {
            cmd.ExecuteNonQuery(); 
        }

        Test2(); 
    }
    // closed after dispose
}

void Test2()
{
    // reuse existing connection 
    using (var ctx = DatabaseContext.GetOpenConnection())
    {
        using (var cmd = ctx.CreateCommand("select 2"))
        {
            cmd.ExecuteNonQuery();
        }
    }
    // leaves connection open
}

Para fines de pruebas automatizadas, generalmente es más fácil pasarlo. Esto se llama inyección de dependencia .

Cuando necesita escribir pruebas, puede crear un objeto de conexión de base de datos simulado y pasarlo en lugar del real. De esa manera, sus pruebas automatizadas no se basarán en una base de datos real que deba ser repoblada con datos cada vez.

Personalmente trabajo para centralizar mi acceso a los datos tanto como sea posible, sin embargo, si no es posible, SIEMPRE abra una nueva conexión en las otras clases, ya que encuentro que hay muchas otras cosas que pueden estorbar al pasar. el objeto de conexión real.

Aquí hay un poco más de información sobre este problema. Tengo una clase que administra conexiones db y tengo 2 clases que implementan una interfaz. Una de las clases es para SQL y la otra es de OLAP. El administrador es el que sabe qué conexión usar, por lo que podría pasar la conexión exacta al tipo, o el tipo puede crear su propia conexión.

Puede pasar objetos de conexión sin ningún problema (por ejemplo, Microsoft Enterprise Library permite que las llamadas a métodos estáticos pasen en una conexión) o puede administrarlo externamente hasta su diseño, no hay concesiones técnicas directas.

Tenga cuidado para que la portabilidad no pase una conexión específica si su solución será portada a otras bases de datos (lo que significa que no pase una SqlConnection si planea trabajar con otras bases de datos)

Configurar la conexión es potencialmente caro y potencialmente agrega un viaje de ida y vuelta. Entonces, nuevamente, potencialmente, el mejor diseño es pasar el objeto de conexión.

Digo potencialmente, porque si eres una aplicación de Microsoft ADO, probablemente estés usando un grupo de conexión ...

Le sugiero que distinga entre el objeto de conexión y su estado (abierto, cerrado).

Puede tener un solo método (o propiedad) que lea la cadena de conexión desde web.config. El uso de la misma versión de la cadena de conexión cada vez garantiza que se beneficiará de la agrupación de conexiones.

Llame a ese método cuando necesite abrir una conexión. En el último momento, después de configurar todas las propiedades de SqlCommand, abra la conexión, úsela y luego ciérrela. En C #, puede usar la instrucción using para asegurarse de que la conexión está cerrada. Si no, asegúrate de cerrar la conexión en un bloque final.

Yo usaría el web.config

<configuration>
    <connectionStrings>
        <add name="conn1" providerName="System.Data.SqlClient" connectionString="string here" />
        <add name="conn2" providerName="System.Data.SqlClient" connectionString="string here" />
    </connectionStrings>
</configuration>

Luego puedes consultarla desde cualquier lugar de la aplicación

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