如何在仅使用一个DbContext实例时处理不同的职责

时间:2011-11-04 14:16:13

标签: asp.net-mvc-3 entity-framework repository-pattern solid-principles

我一直在四处寻找我的问题的答案,但却找不到答案,主要是因为我真的不知道怎么说出来!

我首先使用EF代码并尝试在使用依赖注入的同时实现某种存储库模式(感谢Unity)。我还试图保持SOLID(至少是SRP部分),因为我有IStaffRepositoryIDepartmentRepository接口,后者又实现IRepository<TEntity>,提供基本的CRUD方法。

我的问题是,当我需要更新员工部门时,如何保留SRP?

我已经读过,由于可能存在内存泄漏而对所有存储库使用单个DbContext实例是不好的做法,所以我不能简单地调用IDepartmentRepository来获取新部门,因为这会使用我的DbContext

的单独实例

对我来说,显而易见的解决方案是包含类似......

的内容
Department GetDepartment(int id);

IStaffRepository内 - 但这不会打破SRP吗?

我在Controller中的代码是......

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 个答案:

答案 0 :(得分:1)

如果所有模型都基于同一数据库中的实体,则没有理由不使用单个上下文实例在同一个控制器中管理它们。我会使用简单的解决方案并使用单个上下文实例。

答案 1 :(得分:0)

如果您正在使用Repository模式,那么您至少拥有一个实现一个或多个存储库接口的类。由于您的代码耦合到接口而不是实现,因此您不必担心。但是,您应该将存储库实现视为单例,即每个方法都应该是独立的,并且类不应该存储状态(您可以存储连接字符串,因为它基本上是一个常量)。 所以方法看起来像这样

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

这样你总是处理数据上下文,因此不应该有内存泄漏 对于SRP,存储库的作用是获取/保存对象。如果它做到了那就很好。

答案 2 :(得分:0)

单个实例可能存在的问题是在完成后不释放上下文。如果使用依赖注入,这将在完成后处理此对象的处理。我不建议您使用上面的设计 - 您正在提供ViewModel数据访问行为,这通常不是用于它们的。 ViewModel具有模型的属性,MAYBE具有一些特定于准备数据的功能。将服务层注入控制器,控制器负责填充该视图模型或返回模型。然后,您可以使用automapper将该模型映射到ViewModel。这个映射还有一个很好的属性。

退房: http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/