J'ai besoin d'aide pour mieux comprendre comment Dapper gère les connexions de base de données, et pourquoi DB Connection n'est pas correctement éliminé. J'ai codé autour des différents cas possibles. Dans mon code, je vérifie si la connexion est nulle et crée une nouvelle connexion en conséquence. Sur les demandes en cours, je constate que parfois la connexion est laissée ouverte, et d'autres fois, je trouve que la chaîne de connexion est manquante dans l'objet (le rendant inutilisable, mais ne le définissant pas à NULL). Je traite ces cas en conséquence, mais je voudrais comprendre pourquoi la connexion a ces états variables et n'est pas supprimée même si le code client implémente expressément une instruction using pour envelopper le code. Est-ce la gestion des connexions par ADO.net, y a-t-il un effet secondaire de Dapper ou juste des problèmes avec mon code?
Code de gestion des connexions
public class DatabaseContext : IDatabaseContext
{
private readonly string _connectionString;
private DbConnection _connection;
public DatabaseContext(string connectionString)
{
_connectionString = connectionString;
}
public IDbConnection Connection
{
get
{
if (_connection == null)
_connection = new SqlConnection(_connectionString);
if (string.IsNullOrEmpty(_connection.ConnectionString))
_connection.ConnectionString = _connectionString;
if (_connection.State != ConnectionState.Open)
_connection.Open();
return _connection;
}
}
}
Code client
public IEnumerable<PostSearResults> Search(SearchPostsBy searchPostsBy)
{
DynamicParameters param;
var sql = GetSearchSql(searchPostsBy,out param);//Gets SQL
using (var connection = _databaseContext.Connection)
{
var posts = connection.Query<PostSearResults>(sql, param);
return posts.ToList();
}
}
J'utilise également Dapper dans une application Web et j'implémente un DapperContext similaire au vôtre, mais j'implémente l'IDispose sur la classe comme suit:
#region IDisposable
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
if (transaction != null)
{ transaction.Dispose(); }
if (cn != null)
{ cn.Dispose(); }
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
Ma version de Dapper est celle qui ouvre une connexion si elle est fermée lorsque nous effectuons un appel, elle se ferme ensuite après l'exécution de la requête, si la connexion est ouverte lorsque l'appel effectue simplement exécuter la requête et laisser la connexion ouverte.
J'utilise également DI, donc ma durée de vie DapperContext est gérée par le conteneur DI. Il est donc supprimé lorsque le contexte de la requête Web est terminé et détruit. Mon référentiel Dapper se présente comme suit, avec un exemple de méthode GetPE
private readonly IDbConnection context;
private readonly DapperContext dapperContext;
public SFRepository(DapperContext dbContext)
{
dapperContext = dbContext;
context = dbContext.Connection;
}
public PEData GetPE(int peID)
{
PEData rec = context.Query<PEData>("SELECT * FROM PEDATA WHERE ID= @ID", new { ID = peID }).FirstOrDefault();
return rec;
}
Il a été très stable et je n'ai aucun comportement étrange.