I replace this common statement:
using (var connection = new MySqlConnection(connectionString))
{
connection.Open();
// Do work here; connection closed on following line.
}
With this connection manager class that I made:
public class ConnectionBase : IConnectionBase
{
private static readonly string ConnString =
ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString;
private static readonly Lazy<MySqlConnection> ConnectionString =
new Lazy<MySqlConnection>(() => new MySqlConnection(ConnString));
private IDbConnection _db;
public IDbConnection Db
{
get
{
if (_db != null) return _db;
_db = ConnectionString.Value;
if (_db.State == ConnectionState.Closed) _db.Open();
return _db;
}
}
public void Dispose()
{
if (_db != null)
_db.Dispose();
}
}
And wired up to my repository like this:
public abstract class BaseRepository
{
protected readonly IDbConnection _repository;
public BaseRepository(IConnectionBase connection)
{
_repository = connection.Db;
}
}
Then I use it on top of dapper method (since it's contain connection.close() at the end of every method that it used)
public class MyTableRepository : BaseRepository
{
public MyTableRepository(IConnectionBase connection) : base(connection) {}
public List<MyTable> GetAllMyTable()
{
return _repository.Query("SELECT * FROM MyTable").ToList();
}
}
It's been working great thus far for quite some time in production.
I'm just wondering are there any side effects for this implementation since it doesn't explicitly state to dispose the IDbConnection object?
Update :
As mentioned below, it's not a good idea to share the same instance (singelton) for the connection.
Another variation that we can do is to use delegate like Action
or Func
, like so:
public void WithConnection(Action<IDbConnection> actions)
{
using (var db = new MySqlConnection(ConnString))
{
db.Open();
actions.Invoke(db);
}
}
public void WithTransaction(Action<IDbConnection> actions)
{
using (var db = new MySqlConnection(ConnString))
{
db.Open();
using (var context = db.BeginTransaction())
{
actions.Invoke(db);
context.Commit();
}
}
}
So you can use it like this:
_repository.WithConnection(c =>
{
c.Query<MyTable>("SELECT * FROM MyTable").ToList();
});
Sure it remove the using
statement, but it's still doesn't remove the need of the indentation of the code.
So, in order to correct that, we need a Dependency Injection
implementation that will remove IConnectionBase
object automatically at the end of the scope.