Garantire che la connessione al database si apra e si chiuda ogni volta che utilizzo Dapper per accedere al database

c# dapper database-connection sql sql-server

Domanda

Ecco cosa sto facendo attualmente in una delle mie classi di repository:

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 che voglio fare è mettere la proprietà IDbConnection in un BaseRepository da cui ereditano tutti i miei altri repository. Cosa devo fare per garantire che la mia connessione al database si apra e si chiuda correttamente in ciascuna delle mie funzioni di accesso ai dati come nell'esempio sopra riportato? Ecco cosa faccio attualmente con Entity Framework (usando una dichiarazione su ciascuna funzione, ma ora sto cambiando il DAL per usare pure Dapper:

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;
}

Ho notato negli esempi di Dapper che tutto è racchiuso in un'istruzione usando come mi aspetterei, ma occasionalmente li vedo avvolgere le loro funzioni nel seguito usando:

using (var connection = Program.GetClosedConnection())

GetClosedConnection () restituisce un nuovo SqlConnection, ma qual è la differenza tra i due?

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);
}

Risposta accettata

Ecco come l'ho sempre fatto:

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.
    */
}

Per quanto riguarda la seconda parte della domanda, GetClosedConnection crea semplicemente un'istanza di un oggetto SqlConnection , mentre GetOpenConnection crea un'istanza e apre un oggetto SqlConnection . Tu (o Dapper) dovrai chiamare manualmente Open() sull'oggetto restituito da GetClosedConnection .


Risposta popolare

Questa risposta sarà basata sul tuo desiderio di "evitare la ripetizione".

Crea una classe di estensione di Dapper e metti le funzioni al suo posto e usale. Così:

    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;
    }

E nella parte superiore della classe mettere a

    public SqlConnection activeConnection { get; private set; }

Che è sempre impostato nel costruttore della classe.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché