Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement Unit Of Work pattern with Dapper?

Currently, I am trying to use Dapper ORM with Unit Of Work + Repository Pattern.

I want to use Unit of Work as opposed to a simple dapper Repository due to the fact that my insert and updates require a degree of transaction processing. I have been unable to find any useful examples as most seem to use Entity Framework and have leakage issue within the Unit of Work.

Could someone please point me in the right direction?

like image 801
Stig Avatar asked Jul 08 '15 16:07

Stig


People also ask

Should I use Repository pattern with dapper?

The main advantage to use repository pattern is to isolate the data access logic and business logic, so that if you make changes in any of this logic it can't effect directly on other logic. For more information, please go through the Repository Pattern Article.

How do you implement dapper?

In Visual Studio, create a new console project, and in Solution Explorer right-click References and select Manage NuGet Package Manager and search for Dapper and using the NuGet Package Manager Console command for the Nugget Package Manager “install-package dapper”, and this will install Dapper into your project.

What is unit of work C#?

Unit of Work in C# is the concept that is related to the effective implementation of the Repository Design Pattern. So, to understand this concept it is important to understand the concept of the Repository Pattern.


1 Answers

This Git project is very helpful. I started from the same and did some changes as per my need.

public sealed class DalSession : IDisposable {     public DalSession()     {         _connection = new OleDbConnection(DalCommon.ConnectionString);         _connection.Open();         _unitOfWork = new UnitOfWork(_connection);     }      IDbConnection _connection = null;     UnitOfWork _unitOfWork = null;      public UnitOfWork UnitOfWork     {         get { return _unitOfWork; }     }      public void Dispose()     {         _unitOfWork.Dispose();         _connection.Dispose();     } }  public sealed class UnitOfWork : IUnitOfWork {     internal UnitOfWork(IDbConnection connection)     {         _id = Guid.NewGuid();         _connection = connection;     }      IDbConnection _connection = null;     IDbTransaction _transaction = null;     Guid _id = Guid.Empty;      IDbConnection IUnitOfWork.Connection     {         get { return _connection; }     }     IDbTransaction IUnitOfWork.Transaction     {         get { return _transaction; }     }     Guid IUnitOfWork.Id     {         get { return _id; }     }      public void Begin()     {         _transaction = _connection.BeginTransaction();     }      public void Commit()     {         _transaction.Commit();         Dispose();     }      public void Rollback()     {         _transaction.Rollback();         Dispose();     }      public void Dispose()     {         if(_transaction != null)             _transaction.Dispose();         _transaction = null;     } }  interface IUnitOfWork : IDisposable {     Guid Id { get; }     IDbConnection Connection { get; }     IDbTransaction Transaction { get; }     void Begin();     void Commit();     void Rollback(); } 

Now, your repositories should accept this UnitOfWork in some way. I choose Dependency Injection with Constructor.

public sealed class MyRepository {     public MyRepository(IUnitOfWork unitOfWork)      {         this.unitOfWork = unitOfWork;     }      IUnitOfWork unitOfWork = null;      //You also need to handle other parameters like 'sql', 'param' ect. This is out of scope of this answer.     public MyPoco Get()     {         return unitOfWork.Connection.Query(sql, param, unitOfWork.Transaction, .......);     }      public void Insert(MyPoco poco)     {         return unitOfWork.Connection.Execute(sql, param, unitOfWork.Transaction, .........);     } } 

And then you call it like this:

With transaction:

using(DalSession dalSession = new DalSession()) {     UnitOfWork unitOfWork = dalSession.UnitOfWork;     unitOfWork.Begin();     try     {         //Your database code here         MyRepository myRepository = new MyRepository(unitOfWork);         myRepository.Insert(myPoco);         //You may create other repositories in similar way in same scope of UoW.          unitOfWork.Commit();     }     catch     {         unitOfWork.Rollback();         throw;     } } 

Without Transaction:

using(DalSession dalSession = new DalSession()) {     //Your database code here     MyRepository myRepository = new MyRepository(dalSession.UnitOfWork);//UoW have no effect here as Begin() is not called.     myRepository.Insert(myPoco); } 

Please note that, UnitOfWork is more than DBTransaction.

More details about Repository in above code could be found here.

I have already post this code here. But this question looks more relevant to me for this code; so I am posting again instead of just link to original answer.

like image 110
Amit Joshi Avatar answered Sep 23 '22 01:09

Amit Joshi