Как справиться с разными обязанностями, используя только один экземпляр DbContext - PullRequest
1 голос
/ 04 ноября 2011

Я искал ответ на свой вопрос, но не смог его найти, в основном потому, что не знаю, как его сформулировать!

Сначала я играю с кодом EF и пытаюсьреализовать какой-либо шаблон хранилища, используя внедрение зависимостей (благодаря Unity).Я также пытаюсь придерживаться SOLID (ну, по крайней мере, части SRP) в том смысле, что у меня есть интерфейсы IStaffRepository и IDepartmentRepository, которые, в свою очередь, реализуют IRepository<TEntity>, который обеспечивает базовые CRUD методы.

Мой вопрос: как я могу придерживаться SRP, когда мне нужно обновить отдел персонала?

Я прочитал, что использование одного экземпляра DbContext - это плохая практикадля всех репозиториев из-за возможных утечек памяти, и поэтому я не могу просто позвонить IDepartmentRepository, чтобы получить новый отдел, так как это будет использовать отдельный экземпляр моего DbContext.

Очевидное решение для меня - включитьчто-то вроде ...

Department GetDepartment(int id);

Внутри IStaffRepository - но разве это не нарушит SRP?

Код в моем контроллере: ...

private IStaffRepository repository;
private IDepartmentRepository departmentRepository;

public StaffController(IStaffRepository repository, IDepartmentRepository departmentRepository)
{
   this.repository = repository;
   this.departmentRepository = departmentRepository;
}

public ActionResult Edit(int id)
{
   return View(new StaffViewModel(repository.GetItem(id)));
}

[HttpPost]
public ActionResult Edit(int id, StaffViewModel model)
{
   if (!ModelState.IsValid)
      return View(model);

   var item = repository.GetItem(id);

   // throws error due to different context
   item.Department = departmentRepository.GetItem(int.Parse(model.SelectedDepartment));

   UpdateModel(item, "Item");

   repository.Save();

   return RedirectToAction("Member", new {id});
}

И модель StaffMember содержит ...

public class StaffMember
{
   public virtual Department Department { get; set; }
}

И StaffViewModelвыглядит так ...

public class StaffViewModel : ViewModelBase<StaffMember>
{
   public SelectList DepartmentList {get;set;}
   public string SelectedDepartment {get;set;}

   public StaffViewModel()
   {
      var departmentRepository = new DepartmentRepository();
      DepartmentList = new SelectList(departmentRepository.GetCollection(), "ID", "Title", SelectedDepartment);   
   }

   public StaffViewModel(StaffMember item) : this()
   {
      Item = item;
      SelectedDepartment = Item.Department.ID.ToString();
   }

   public StaffViewModel(List<StaffMember> collection) : this()
   {
      Collection = collection;
   }
}  

В базе данных есть поле int Department_ID, которое подключается к таблице Department.

У меня есть раскрывающийся список, который выглядит как...

@Html.DropDownListFor(m => m.SelectedDepartment, Model.DepartmentList, "--Please Select--")

Извиняюсь за длину этого вопроса!

Ответы [ 3 ]

1 голос
/ 04 ноября 2011

Если все ваши модели основаны на объектах в одной базе данных, нет причин не использовать один экземпляр контекста для управления ими в одном контроллере.Я хотел бы пойти с простым решением и использовать один экземпляр контекста.

0 голосов
/ 04 ноября 2011

Проблема, возможно, с одним экземпляром не освобождает контекст, когда это сделано. Если вы используете внедрение зависимостей, это будет обрабатывать удаление этого объекта, когда это будет сделано. Я также не рекомендую дизайн, который у вас есть выше - вы задаете поведение доступа к данным ViewModel, для которого они обычно не предназначены. ViewModel имеет свойства для модели и МОЖЕТ иметь некоторые функции, специфичные для подготовки этих данных. Внедрите сервисный уровень в свой контроллер, обязанность которого состоит в том, чтобы заполнить эту модель представления ИЛИ вернуть модель. Затем вы можете просто использовать automapper, чтобы сопоставить эту модель с вашей ViewModel. Для этого сопоставления также имеется аккуратный атрибут.

Выезд: http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/

0 голосов
/ 04 ноября 2011

Если вы используете шаблон Repository, то у вас есть по крайней мере класс, который реализует один из нескольких интерфейсов репозитория.Поскольку ваш код связан с интерфейсом, а не с реализацией, вам не о чем беспокоиться.Тем не менее, вы должны рассматривать реализацию репозитория как одноэлементную, то есть каждый метод должен быть независимым, а класс не должен хранить состояние (вы можете хранить строку соединения, поскольку она в основном является константой).Таким образом, метод выглядит следующим образом:

public void Save(Entity entity)
{
   using(var db=new MyDbContext())
   {
      //do stuff
   }
}

Таким образом, вы всегда избавляетесь от контекста данных и, следовательно, не должно быть утечек памяти. Что касается SRP, роль хранилища заключается в получении / сохранении объектов.Если это так, то это хорошо.

...