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?
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.