I've been playing with Dapper, but I'm not sure of the best way to handle the database connection.
Most examples show the connection object being created in the example class, or even in each method. But it feels wrong to me to reference a connection string in every clss, even if it's pulling from the web.config.
My experience has been with using a DbDataContext
or DbContext
with Linq to SQL or Entity Framework, so this is new to me.
How do I structure my web apps when using Dapper as my Data Access strategy?
Try this:
Best practice is a real loaded term. I like a
DbDataContext
style container like Dapper.Rainbow promotes. It allows you to couple theCommandTimeout
, transaction and other helpers.For example:
I do it like this:
Then, wherever I wire-up my dependencies (ex: Global.asax.cs or Startup.cs), I do something like:
Everyone appears to be opening their connections entirely too early? I had this same question, and after digging through the Source here - https://github.com/StackExchange/dapper-dot-net/blob/master/Dapper/SqlMapper.cs
You will find that every interaction with the database checks the connection to see if it is closed, and opens it as necessary. Due to this, we simply utilize using statements like above without the conn.open(). This way the connection is opened as close to the interaction as possible. If you notice, it also immediately closes the connection. This will also be quicker than it closing automatically during disposal.
One of the many examples of this from the repo above:
Below is a small example of how we use a Wrapper for Dapper called the DapperWrapper. This allows us to wrap all of the Dapper and Simple Crud methods to manage connections, provide security, logging, etc.
Microsoft.AspNetCore.All: v2.0.3 | Dapper: v1.50.2
I am not sure if I am using the best practices correctly or not, but I am doing it this way, in order to handle multiple connection strings.
It's easy if you have only 1 connection string
Startup.cs
DiameterRepository.cs
Problems if you have more than 1 connection string
Since
Dapper
utilizesIDbConnection
, you need to think of a way to differentiate different database connections.I tried to create multiple interfaces, 'inherited' from
IDbConnection
, corresponding to different database connections, and injectSqlConnection
with different database connection strings onStartup
.That failed because
SqlConnection
inherits fromDbConnection
, andDbConnection
inplements not onlyIDbConnection
but alsoComponent
class. So your custom interfaces won't be able to use just theSqlConnection
implenentation.I also tried to create my own
DbConnection
class that takes different connection string. That's too complicated because you have to implement all the methods fromDbConnection
class. You lost the help fromSqlConnection
.What I end up doing
Startup
, I loaded all connection string values into a dictionary. I also created anenum
for all the database connection names to avoid magic strings.IDbConnection
, I createdIDbConnectionFactory
and injected that as Transient for all repositories. Now all repositories takeIDbConnectionFactory
instead ofIDbConnection
.DatabaseConnectionName.cs
IDbConnectionFactory.cs
DapperDbConenctionFactory - my own factory implementation
Startup.cs
DiameterRepository.cs
DbConnection1RepositoryBase.cs
Then for other repositories that need to talk to the other connections, you can create a different repository base class for them.
Hope all these help.
It was asked about 4 years ago... but anyway, maybe the answer will be useful to someone here:
I do it like this in all the projects. First, I create a base class which contains a few helper methods like this:
And having such a base class I can easily create real repositories without any boilerplate code:
So all the code related to Dapper, SqlConnection-s and other database access stuff is located in one place (BaseRepository). All real repositories are clean and simple 1-line methods.
I hope it will help someone.