Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net - Decoupling Unit of Work pattern for multiple ORM's

My current application structure is:

  • Models assembly
  • Data assembly
    • Defines repository interfaces to be implemented by an ORM
  • ORM assembly
    • Implements repository interfaces from Data assembly
    • Uses unity (IoC container) to regsister Data.IRepository<> to ORM.GenericRepository<>
  • Business assembly
    • References the Data and Models assemblies
    • Uses unity to resolve types of IRepository<>
  • UI assembly
    • References the Business assembly

This structure has essentially decoupled the Business layer from the ORM implementing the IRepository<T>.

One of the benefits of this decoupled structure is that I should be able to replace the ORM relatively easily - for example, move from Entity Framework to NHibernate or just upgrading an existing ORM. I'm currently using EF 4.1 code first and am building another assembly for NHibernate.

I'm considering implementing the Unit of Work pattern.

I've read that this pattern should be used in the business layer (with interfaces defined in my Data assembly, and implemented in the ORM assembly just like I did with the repository pattern). Currently, all instantiated repositories have their own DbContext / session and its lifetime is set to that of the repository - which may be bad- my problem is that I'm not sure if its possible to implement a Unit of Work pattern that would work with different ORM's (er rather, it probably is and I'm just not up to speed).

This is the only thing that comes to mind:

Create IUnitOfWork in my Data assembly that has a function: object GetCurrentSession(); , then have an argument in the constructor of the repositorys in the ORM assembly and cast it to the appropriate session / DbContext (If NHibernate then ISession, if Entity Framework then DbContext)

I would appreciate if anyone has some insight into this situation.

like image 901
Chris Klepeis Avatar asked Nov 26 '22 14:11

Chris Klepeis


1 Answers

Recently I made my research project where I implemented a simple ASP.NET Core CRUD API using unit of work and repository patterns. I made it so that my API controller works with persistent storage only via IUnitOfWork abstraction. And I have separate projects for Dapper, Entity Framework Core and NHibernate, each of them implements IUnitOfWork for specific ORM.

Here's the project link: https://github.com/pkirilin/UnitOfWorkExample

Here's a simple example:

class SomeService
{
    private readonly IAppUnitOfWork _unitOfWork;

    // IAppUnitOfWork is inherited from base IUnitOfWork and added to DI container
    public SomeService(IAppUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public async Task DoSomethingAsync(CancellationToken cancellationToken)
    {
        var entity = await _unitOfWork.WeatherForecasts.GetByIdAsync(..., cancellationToken);
        _unitOfWork.WeatherForecasts.Delete(entity);

        var newEntity = new WeatherForecast(...);
        _unitOfWork.WeatherForecasts.Add(newEntity);

        await _unitOfWork.SaveChangesAsync(cancellationToken);
    }
}
like image 136
pkirilin Avatar answered Nov 28 '22 02:11

pkirilin