Реализация UnitOfWork
Мне удалось реализовать небольшой классный блок работы для работы с сущностью.
Я придумал..
public class UnitOfWork : IUnitOfWork
{
private Database _database;
private IDatabaseFactory _databaseFactory;
private DbTransaction transaction;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
_databaseFactory = databaseFactory;
_database = Database;
transaction = _database.Database.Connection.BeginTransaction();
}
public Database Database
{
get { return _database ?? (_database = _databaseFactory.Get()); }
}
public void Dispose()
{
try
{
_database.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
}
}
}
Я уверен, что все завидуют этой единице работы сейчас. (Шучу)
Но у меня есть небольшая проблема дизайна в этом слое обслуживания.
public class JournalService : IJournalService
{
IJournalRepository _journalRepository;
public JournalService(IJournalRepository journalRepository)
{
_journalRepository = journalRepository;
}
public void AjouterJournal(Journal j)
{
[B]using (IUnitOfWork uow = new UnitOfWork())[/B]
{
var journal = new Journal();
journalRepository.AddJournal(journal);
}
}
}
Проблема в том, что единице работы нужна инъекция базы данных, поэтому я не могу создать ее экземпляр. Я не могу предоставить единицу работы непосредственно на уровне обслуживания, потому что это не имеет смысла, поскольку единица работы должна быть одноразовой.
И поскольку я использую репозиторий для добавления своих материалов, нет необходимости напрямую обращаться к единице работы, сохранение будет происходить автоматически, когда оно все равно будет утилизировано.
Я мог бы внедрить IDatabaseFactory в свой сервисный слой, но идея в том, чтобы не использовать его там. На самом деле сервисный уровень не должен знать об этом.
Как насчет фабрики UnitOfWork?
Любые идеи или предложения о том, как я могу это исправить?
Благодарю.
1 ответ
Вы должны внедрить UnitOfWork в сервис, если хотите использовать вашу текущую архитектуру. Ваш сервис не будет иметь внутренней (скрытой) зависимости от реализации UnitOfWork, и он будет лучше тестируемым. Он идет рука об руку со многими принципами объектно-ориентированной архитектуры.
Другое дело, что эта реализация может использоваться только для простых операций CRUD. В более сложных сервисах вы в итоге составите несколько операций (возможно, из нескольких сервисов), каждая из которых будет работать с UnitOfWork. Вызов нескольких SaveChanges (и транзакций) в одной бизнес-операции, вероятно, не то, что вы обычно хотите - в таком случае вы хотите вызывать SaveChanges только один раз из какой-либо службы верхнего уровня или из вызывающей стороны службы. Типичный сценарий состоит в том, что одна бизнес-операция имеет одну единицу работы с одной транзакцией, но вы можете выполнять множество операций службы как часть этой бизнес-операции.
Еще одним следствием является создание ваших хранилищ. Возможно, им нужен доступ к базе данных, не так ли? Таким образом, вы, вероятно, уже внедрили UoW в конструктор хранилища. Если вы сделаете это, вы сможете вообще избежать связи между UoW и базовыми сервисами.