Reputation: 168
I developed an ASP.NET MVC application to manage projects, using Entity Framework 6.0 and the Repository design pattern. Now I want to integrate transactions in order to insure that some insert/update database operations respect the ACID principal and especially the atomicity principal.
Below is a snippets of my Generic repository :
1. Generic repository interface
public interface IGenericRepository<T> : IRepository where T : BaseEntity
{
void Create(T entity);
void Delete(T entity);
IEnumerable<T> GetAll();
void Update(T entity);
}
2. Generic repository class
public abstract class GenericRepository<T> : IGenericRepository<T> where T : BaseEntity
{
protected IContext _context;
protected IDbSet<T> _dbset;
public GenericRepository(IContext context)
{
_context = context;
_dbset = _context.Set<T>();
}
public virtual void Create(T entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
_dbset.Add(entity);
_context.SaveChanges();
}
public virtual void Update(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
_context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
_context.SaveChanges();
}
public virtual void Delete(T entity)
{
if (entity == null) throw new ArgumentNullException("entity");
_dbset.Remove(entity);
_context.SaveChanges();
}
public virtual IEnumerable<T> GetAll()
{
return _dbset.AsEnumerable<T>();
}
}
3. My Icontext implementation
public interface IContext
{
IDbSet<Projet> Projects { get; set; }
IDbSet<Task> Tasks{ get; set; }
IDbSet<Entite> Entities { get; set; }
DbSet<TEntity> Set<TEntity>() where TEntity : class;
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
int SaveChanges();
}
4. The Project Entity
public class ProjectRepository : GenericRepository<Projet>, IProjectRepository
{
IContext _context;
public ProjectRepository(IContext context) : base(context)
{
_context = context;
_dbset = _context.Set<Projet>();
}
public Projet GetProjectById(int Id)
{
return _dbset.FirstOrDefault(x=>x.Id == Id);
}
}
So, what I want to do, is to have transactions work with the model above. For example, when a project is created with his tasks I want to use a transaction to save the Project and the Task entities, so I'm sure that the insert of theses entities would be an atomic operation.
thanks for your help and suggestions.
Upvotes: 3
Views: 5592
Reputation: 908
Usually, your repositories are injected into engine / service classes. I will assume we have a ProjectEngine.cs where ProjectRepo and TaskRepo are injected. The code will look as follows:
public class ProjectEngine : IProjectEngine
{
IProjectRepository projectRepository;
ITaskRepository taskRepository;
public ProjectEngine(
IProjectRepository ProjectRepository,
ITaskRepository TaskRepository)
{
projectRepository = ProjectRepository;
taskRepository = TaskRepository;
}
public void CreateProject(CreateProjectRequest createProjectRequest)
{
using (TransactionScope scope = new TransactionScope())
{
// these operations are atomic since they below to same transactionscope
projectRepository.Add([project]);
taskRepository.Add([tasks]);
// data will not be affected until complete operation is called. Any database exception would rollback the transaction.
scope.Complete();
}
}
}
To recap, the best way to do that is by including multiple repositories operations within same transactionscope.
Upvotes: 6