Asegurar que la conexión de la base de datos se abra y se cierre cada vez que uso Dapper para acceder a la base de datos

c# dapper database-connection sql sql-server

Pregunta

Esto es lo que estoy haciendo actualmente en una de mis clases de repositorio:

private IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnString"].ConnectionString);

public IEnumerable<Product> GetProducts(int categoryId = null, bool? active = null)
{
    StringBuilder sql = new StringBuilder();
    sql.AppendLine("SELECT * ");
    sql.AppendLine("FROM Product ");
    sql.AppendLine("WHERE @CategoryId IS NULL OR CategoryId = @CategoryId ");
    sql.AppendLine("  AND @Active IS NULL OR Active = @Active");

    return this.db.Query<Product>(sql.ToString(), new { CategoryId = categoryId, Active = active }).ToList();
}

Una cosa que quiero hacer es poner la propiedad IDbConnection en un BaseRepository del que todos mis otros repos heredan. ¿Qué debo hacer para asegurar que mi conexión a la base de datos se abra y se cierre correctamente en cada una de mis funciones de acceso a datos como en el ejemplo anterior? Esto es lo que hago actualmente con Entity Framework (con una instrucción using alrededor de cada función, pero ahora estoy cambiando el DAL para usar Dapper puro:

using (var context = new MyAppContext())
{
    var objList = (from p in context.Products
                   where (categoryId == null || p.CategoryId == categoryId) &&
                         (active == null || p.Active == active)
                   select p).ToList();

    return objList;
}

Noté en los ejemplos de Dapper que todo está envuelto en una declaración de uso como lo esperaría, pero ocasionalmente los veo envolviendo sus funciones en el siguiente uso:

using (var connection = Program.GetClosedConnection())

GetClosedConnection () devuelve un nuevo SqlConnection, pero ¿cuál es la diferencia entre los dos?

public static SqlConnection GetOpenConnection(bool mars = false)
{
    var cs = connectionString;
    if (mars)
    {
        SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder(cs);
        scsb.MultipleActiveResultSets = true;
        cs = scsb.ConnectionString;
    }
    var connection = new SqlConnection(cs);
    connection.Open();
    return connection;
}
public static SqlConnection GetClosedConnection()
{
    return new SqlConnection(connectionString);
}

Respuesta aceptada

Así es como siempre he hecho eso:

SqlConnection dbConnection;
using (dbConnection = new SqlConnection(connectionString))
{
    /* 
       Whatever Dapper stuff you want to do. Dapper will open the
       connection and the using will tear it down.
    */
}

En cuanto a la segunda parte de su pregunta, GetClosedConnection simplemente GetClosedConnection una instancia de un objeto SqlConnection , mientras que GetOpenConnection instancia y abre un objeto SqlConnection . Usted (o Dapper) tendrá que llamar manualmente a Open() en el objeto devuelto por GetClosedConnection .


Respuesta popular

Esta respuesta se basará en su deseo de "evitar la repetición".

Haz una clase de extensión de Dapper y pon funciones en ella y úsala en su lugar. Al igual que:

    public IEnumerable<T> Query<T>(string sqlQuery, object parameters = null)
    {
        this.activeConnection.Open();

        var result = this.activeConnection
            .Query<T>(sqlQuery, parameters);

        this.activeConnection.Close();

        return result;
    }

Y en la parte superior de la clase, pon un

    public SqlConnection activeConnection { get; private set; }

Que siempre se establece en el constructor de la clase.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué