我一直在四处寻找我的问题的答案,但却找不到答案,主要是因为我真的不知道怎么说出来!
我首先使用EF代码并尝试在使用依赖注入的同时实现某种存储库模式(感谢Unity)。我还试图保持SOLID(至少是SRP部分),因为我有IStaffRepository
和IDepartmentRepository
接口,后者又实现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--")
对这个问题的篇幅深表抱歉!
答案 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/