.Net Core App -Repository Pattern and Unit of Work with transaction using Dapper

Baala Srinivas
3 min readMay 10, 2021

--

Photo by Kari Shea on Unsplash

“Keep it Simple” is the motivation behind the creation of Dapper.

What is Dapper?

Dapper is a light weight Object-Relational Mapping (ORM) framework developed by Stack Exchange (brains behind Stack Overflow)

The moment we hear this acronym ORM first thing which comes to mind for a .Net developer is Entity Framework. Dapper is also a similar kind of framework but we can consider Dapper as a “Micro-ORM” because EF provides wide range of features when compared to Dapper.

Cool, now lets get into code

In this example I am going to use a simple money transfer scenario.

User A can send money to user B and the transaction detail will be persisted in database for future reference

Architecture

Repository

Lets gets started by creating a repository

Our use case needs two repositories

  1. User Repository for managing user account operations
  2. Transfer Repository for tracking the money transfers

We will be injecting SqlConnection using which we will be performing the CRUD operations and we also be injecting IDBTransaction instance to repository.

This can be done in individually in each repository or we can create a base repository with these properties and other repositories can inherit the base repository.

All the dapper methods are extension methods to SqlConnection class type and we have an optional parameter to pass the transaction instance.

For transaction we don't have any special class from Dapper, we will be using IDBTransaction which we normally use for SqlConnection transactions.

Below is the sample repository code

Unit of work

The main reason behind unit of work is to minimize the number of calls made to database. Unit of work will keep track of the changes made to entities and finally push the changes in to database on commit. Same pattern can be used to maintain a transaction.

A single application can have multiple entities and repositories. We can expose all the repository instances via unit of work which a controller or consumer can use.

In our case we will be injecting IDBTransaction instance and repository instances to our unit of work class.

Unit of work will expose a commit method using which the client can save the changes to db.

In our case we will be calling commit method exposed by the IDBTransaction inside our commit method, in case if there is any exception we can roll back the transaction.

Now lets move on to core part of the implementation

Startup.cs

We need to share same IDBTransaction instance across the repository and the unit of work for a given request cycle, so we can inject it as a scoped instance.

In order to obtain this instance we need a SQL connection, so lets inject a SqlConnection as a scoped instance and from that we can obtain transaction instance from this connection

Lets consume the service from controller

Controller.cs

Lets write our business logic in controller and commit the changes using unit of work instance.

Note: Since we inject the transaction instance from Startup.cs all the queries which are executed as part of the same SqlConnection will require a transaction instance.

Complete code can be found in this GitHub repo

Please feel free to share your thoughts or feedback in comments section. In case if this article helped you to learn something please leave a clap below

Happy Coding !!!

--

--