Reputation: 181
need you help implementing UnitOfWork for my business layer. Want to wrap multiple different business service calls into a single transaction. Let's assume I use Entity Framework as my repository layer and I have an additional business layer for validation and other business rules. In this example just very very simple.
public class MyDbContext
{
public DbSet<User> Users;
public DbSet<Contract> Contracts;
}
public class UserService
{
public UserService(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public void AddUser(User user)
{
_dbContext.Users.Add(user);
_dbContext.SaveChanges();
}
}
public class ContractService
{
public ContractService(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public void AddContract(Contract contract)
{
_dbContext.Contracts.Add(contract);
_dbContext.SaveChanges();
}
}
In my controller:
userService.AddUser(user);
contractService.AddContract(contract);
... The add user calls already save changes but i want to save changes after add contract. So can I do the following?? Or is this somehow bad design?!
Create UnitOfWork class:
public class UnitOfWork
{
public UnitOfWork(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public MyDbContext DbContext => _dbContext;
public void SaveChanges()
{
_dbContext.SaveChanges();
}
}
Change my services to:
public class UserService
{
public UserService(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void AddUser(User user)
{
_unitOfWork.DbContext.Users.Add(user);
}
}
public class ContractService
{
public ContractService(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void AddContract(Contract contract)
{
_unitOfWork.DbContext.Contracts.Add(contract);
}
}
And then in my controller I do:
userService.AddUser(user);
contractService.AddContract(contract);
unitOfWork.SaveChanges();
Is this a valid approach?! Really need your help and thoughts on this...
Thanks!!!!
Upvotes: 0
Views: 315
Reputation: 4633
Your 'UnitOfWork' should contain methods that reflect your use cases. So I would have a method like 'CreateContract' which actually adds the 'user' and 'contract' and commits the transaction and just call this method from the controller.
public void CreateContract(User user,Contract contract)
{
this.dbContext.Users.Add(user);
this.dbContext.Contracts.Add(contract);
this.dbContext.SaveChanges();
}
This way you can encapsulate any transactional code within this method. Ex - if adding a user and contract are not simply EF calls but calls to different services, you can have a distributed transaction or other code to rollback the transaction.
Upvotes: 0