0

I am developing a .NET Core application where I leverage the Generic Repository pattern and I would like to know how can I implement a transaction:

IGenericRepository

public interface IGenericRepository<T>
    {
        Task InsertAsync(T insert);
        Task<bool> RemoveAsync(object id);
        Task UpdateAsync(T entity);
        Task<T> GetByIdAsync(object id,string includeProperties="");
        Task<IQueryable<T>> GetAsync(Expression<Func<T, bool>> filter=null,
                                     int? skip=null,
                                     int? take=null,
                                     Func<IQueryable<T>,IOrderedQueryable<T>> orderBy = null,
                                     string includeProperties = "");
        Task SaveAsync();
    }

I was looking at this implementation which uses UnitOfWork as well, but in .NET Core, I do not have a DbContextTransaction.

I am not using UnitOfWork yet. Currently my service looks like this:

public class SomeService
{
   IGenericRepository<A> arepo;
   IGenericRepository<B> brepo;
   public SomeService(IGenericRepository<A> arepo,IGenericRepository<B> brepo)
   {
        this.arepo=arepo;
        this.brepo=brepo;
   }
   public async Task DoTransaction(id)
   {
        var a=await arepo.GeyById(id)
        await brepo.RemoveAsync(a.Id);
        await brepo.SaveChangesAsync();
        await arepo.InsertAsync([something]);
        await arepo.SaveChanges();
   }  
}

I would want to make this transactional and also, avoid using SaveChangesAsync for all repositories that get involved.

What would be a solution?

Amit Joshi
  • 15,448
  • 21
  • 77
  • 141
Bercovici Adrian
  • 8,794
  • 17
  • 73
  • 152
  • 1
    EF Core already has implemented repository and UoW patterns. Is there any specific need to wrap it? Some interesting post for you that probably will clarify what i am talking about: https://gunnarpeipman.com/ef-core-repository-unit-of-work/ – Krystian Sitek Jan 07 '20 at 10:24

1 Answers1

1

Well I am not expert in entity framework, but I am answering in terms of repository and unit of work.

To begin with, avoid unnecessary wrapper of additional generic repository as you are already using full-ORM. Please refer to this answer.

but in .NET Core i do not have a DbContextTransaction.

The DbContextTransaction is important but not a key for implementing unit of work in this case. What is important is DBContext. It is DBContext that tracks and flushes the changes. You call SaveChanges on DBContext to notify that you are done.

I would want to make this transactional

I am sure there must be something available to replace DbContextTransaction or to represent transaction.

One way suggested by Microsoft is to use it as below:

context.Database.BeginTransaction()

where context is DbContext.

Other way is explained here.

also ,avoid using SaveChangesAsync for all repos that get involved

That is possible. Do not put SaveChanges in repositories. Put it in separate class. Inject that class in each concrete/generic repository. Finally, simply call SaveChanges once when you are done. For sample code, you can have a look at this question. But, code in that question have a bug which is fixed in the answer I provided to it.

Amit Joshi
  • 15,448
  • 21
  • 77
  • 141