Создание нового проекта MVC и идея создания репозиториев в слое данных, поэтому я их реализовал. Я также создал слой Service для обработки всей бизнес-логики и проверки, этот слой, в свою очередь, использует соответствующий репозиторий. Что-то вроде этого (я использую простой инжектор для инъекций)
DAL LAYER
public MyRepository() {
private DbContext _context;
public MyRepository(DbContext context) {
_context = context;
}
public MyEntity Get(int id)
{
return _context.Set<MyEntity>().Find(id);
}
public TEntity Add(MyEntity t)
{
_context.Set<MyEntity>().Add(t);
_context.SaveChanges();
return t;
}
public TEntity Update(MyEntity updated, int key)
{
if (updated == null)
return null;
MyEntity existing = _context.Set<MyEntity>().Find(key);
if (existing != null)
{
_context.Entry(existing).CurrentValues.SetValues(updated);
_context.SaveChanges();
}
return existing;
}
public void Delete(MyEntity t)
{
_context.Set<MyEntity>().Remove(t);
_context.SaveChanges();
}
}
СЕРВИСНЫЙ СЛОЙ
public MyService() {
private MyRepository _repository;
public MyService(MyRepository repository) {
_repository = repository;
}
public MyEntity Get(int id)
{
return _repository.Get(id);
}
public MyEntity Add(MyEntity t)
{
_repository.Add(t);
return t;
}
public MyEntity Update(MyEntity updated)
{
return _repository.Update(updated, updated.Id);
}
public void Delete(MyEntity t)
{
_repository.Delete(t);
}
}
Теперь это очень просто, поэтому я могу использовать следующий код для обновления объекта.
MyEntity entity = MyService.Get(123);
MyEntity.Name = "HELLO WORLD";
entity = MyService.Update(entity);
Или это для создания объекта
MyEntity entity = new MyEntity();
MyEntity.Name = "HELLO WORLD";
entity = MyService.Add(entity);
// entity.Id is now populated
Теперь скажите, что мне нужно обновить элемент, основанный на идентификаторе создания другого, я мог бы использовать код, прежде всего отлично, но что произойдет, если произошла ошибка? Мне нужна какая-то транзакция/откат. Это то, что, по-видимому, решит модель "Единица работы"?
Итак, я думаю, мне нужно иметь DbContext в моем объекте UnitOfWork, поэтому я создаю такой объект?
public UnitOfWork() : IDisposable {
private DbContext _context;
public UnitOfWork(DbContext context) {
_context = context;
}
public Commit() {
_context.SaveChanges();
}
public Dispose() {
_context.Dispose();
}
}
Хорошо, снова, это довольно просто. UnitOfWork также поддерживает контекст (во всяком случае, я использую такой же контекст во всех репозиториях), и он вызывает метод SaveChanges(). Затем я удалил вызов метода SaveChanges() из моего репозитория. Поэтому для добавления я бы сделал следующее:
UnitOfWork uow = new UnitOfWork(new DbContext()); // i would inject this somehow
MyEntity entity = new MyEntity();
MyEntity.Name = "HELLO WORLD";
entity = MyService.Add(entity);
uow.Commit();
Но что, если мне нужно создать объект, а затем обновить другие объекты на основе этого Идентификатора, это теперь не сработает, потому что Id не будет создан, пока я не назову Commit на uow. Пример
UnitOfWork uow = new UnitOfWork(new DbContext()); // i would inject this somehow
MyEntity entity = new MyEntity();
MyEntity.Name = "HELLO WORLD";
entity = MyService.Add(entity);
// entity.Id is NOT populated
MyEntity otherEntity = MyService.Get(123);
otherEntity.OtherProperty = entity.Id;
MyService.Update(otherEntity);
uow.Commit(); // otherEntity.OtherProperty is not linked.....?
Итак, у меня такое чувство, что этот класс UnitOfWork не прав... может быть, я пропустил понимание чего-то.
Мне нужно иметь возможность добавлять сущность и получать этот идентификатор и использовать его на другом объекте, но если возникает ошибка, я хочу "откат", как это сделала бы транзакция ado.net.
Возможно ли использование этой функции с использованием Entity Framework и репозиториев?