patterncsharpMinor
Manage connection without 'using' statement
Viewed 0 times
withoutstatementmanageusingconnection
Problem
I replace this common statement:
With this connection manager class that I made:
And wired up to my repository like this:
Then I use it on top of the
It's been working great thus far for quite some time in production.
Are there any side effects for this implementation since it doesn't explicitly state to dispose the
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 ConnectionString =
new Lazy(() => 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 the
dapper method (since it contains connection.close() at the end of every method that it used).public class MyTableRepository : BaseRepository
{
public MyTableRepository(IConnectionBase connection) : base(connection) {}
public List GetAllMyTable()
{
return _repository.Query("SELECT * FROM MyTable").ToList();
}
}It's been working great thus far for quite some time in production.
Are there any side effects for this implementation since it doesn't explicitly state to dispose the
IDbConnection object?Solution
I can understand why you want to remove the clutter from your code - but sharing the instance of
The connections are already pooled for you (See here) so you creating and disposing
I think you should create a connection factory:
Then your base repository can do:
Then all of your actual repositories can do:
I realise it doesn't save you much over the original code other than centralising the connection string...
A more advanced idea would be add an
MySqlConnection isn't a good idea. As soon as multiple threads are trying to use the connection at the same time, things are going to go wrong.The connections are already pooled for you (See here) so you creating and disposing
IDbConnections is cheap and easy.I think you should create a connection factory:
public interface IConnectionFactory
{
IDbConnection GetOpenConnection();
}
public class ConnectionFactory : IConnectionFactory
{
private static readonly string connectionString =
ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString;
public IDbConnection GetOpenConnection()
{
// Is there an overload to automatically open the connection?
var connection = new MySqlConnection(connectionString);
connection.Open();
return connection;
}
}Then your base repository can do:
public abstract class BaseRepository
{
protected readonly IConnectionFactory connectionFactory;
public BaseRepository(IConnectionFactory connectionFactory)
{
this.connectionFactory = connectionFactory;
}
}Then all of your actual repositories can do:
public class MyTableRepository : BaseRepository
{
public MyTableRepository(IConnectionFactory connectionFactory) : base(connectionFactory) {}
public List GetAllMyTable()
{
using (var connection = connectionFactory.GetOpenConnection())
{
return connection.Query("SELECT * FROM MyTable").ToList();
}
}
}I realise it doesn't save you much over the original code other than centralising the connection string...
A more advanced idea would be add an
Execute method to your base repo but I don't think it would add much...protected T Execute(Func query)
{
using (var connection = connectionFactory.GetOpenConnection())
{
return query(connection);
}
}Code Snippets
public interface IConnectionFactory
{
IDbConnection GetOpenConnection();
}
public class ConnectionFactory : IConnectionFactory
{
private static readonly string connectionString =
ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString;
public IDbConnection GetOpenConnection()
{
// Is there an overload to automatically open the connection?
var connection = new MySqlConnection(connectionString);
connection.Open();
return connection;
}
}public abstract class BaseRepository
{
protected readonly IConnectionFactory connectionFactory;
public BaseRepository(IConnectionFactory connectionFactory)
{
this.connectionFactory = connectionFactory;
}
}public class MyTableRepository : BaseRepository
{
public MyTableRepository(IConnectionFactory connectionFactory) : base(connectionFactory) {}
public List<MyTable> GetAllMyTable()
{
using (var connection = connectionFactory.GetOpenConnection())
{
return connection.Query("SELECT * FROM MyTable").ToList();
}
}
}protected T Execute<T>(Func<IDbConnection, T> query)
{
using (var connection = connectionFactory.GetOpenConnection())
{
return query(connection);
}
}Context
StackExchange Code Review Q#87608, answer score: 8
Revisions (0)
No revisions yet.