ASP.NET MVC UnitOfWork и Бизнес-сервисы / Уровень
Нужна ваша помощь в реализации UnitOfWork для моего бизнес-уровня. Хотите объединить несколько разных вызовов бизнес-сервисов в одну транзакцию. Давайте предположим, что я использую Entity Framework в качестве своего уровня хранилища, и у меня есть дополнительный бизнес-уровень для проверки и других бизнес-правил. В этом примере просто очень, очень просто.
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();
}
}
В моем контроллере:
userService.AddUser(user);
contractService.AddContract(contract);
... Добавленные пользовательские вызовы уже сохраняют изменения, но я хочу сохранить изменения после добавления контракта. Так я могу сделать следующее? Или это как-то плохой дизайн?!
Создайте класс UnitOfWork:
public class UnitOfWork
{
public UnitOfWork(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public MyDbContext DbContext => _dbContext;
public void SaveChanges()
{
_dbContext.SaveChanges();
}
}
Измените мои услуги на:
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);
}
}
И тогда в моем контроллере я делаю:
userService.AddUser(user);
contractService.AddContract(contract);
unitOfWork.SaveChanges();
Это правильный подход?! Очень нужна ваша помощь и мысли по этому поводу...
Спасибо!!!!
1 ответ
Ваш "UnitOfWork" должен содержать методы, отражающие ваши варианты использования. Таким образом, у меня был бы такой метод, как "CreateContract", который фактически добавляет "user" и "contract", фиксирует транзакцию и просто вызывает этот метод из контроллера.
public void CreateContract(User user,Contract contract)
{
this.dbContext.Users.Add(user);
this.dbContext.Contracts.Add(contract);
this.dbContext.SaveChanges();
}
Таким образом, вы можете инкапсулировать любой транзакционный код в этом методе. Например, если добавление пользователя и контракта - это не просто вызовы EF, а вызовы различных служб, вы можете использовать распределенную транзакцию или другой код для отката транзакции.