如何处理不同的责任只使用一个DbContext实例 [英] How to handle different responsibilities while using only one instance of DbContext
问题描述
我我首先使用EF代码,并尝试使用依赖注入来实现某种存储库模式(感谢Unity)。我也试图保持SOLID(至少是SRP部分),因为我有 IStaffRepository
和 IDepartmentRepository
这些接口又实现了提供基本的 CRUD
方法的 IRepository< TEntity>
我的问题是,当我需要更新工作人员的部门时,如何保持SRP?
我已经看到,由于可能的内存泄漏,所有存储库都使用单个 DbContext
实例是不好的做法,所以我不能简单地调用 IDepartmentRepository
来获取新的部门,因为这将使用我的 DbContext
的单独实例。
对我来说,明显的解决方案是包括一些...
部门GetDepartment(int id);
在 IStaffRepository
- 但这不会打破SRP?
我的控制器中的代码是...
私有IStaffRepository存储库;
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);
//由于不同的上下文导致错误
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;组; }
}
而 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>集合):this()
{
Collection = collection;
}
}
在数据库中有一个 int Department_ID
字段挂接到Department表。
我的视图中有一个下拉,看起来像...
@ Html.DropDownListFor(m => m.SelectedDepartment,Model.DepartmentList, - 请选择 - )
对这个问题的长度表示歉意!
如果所有的模型都是基于同一数据库中的实体,那么没有理由不使用单个上下文实例在同一个控制器中进行管理。我将使用简单的解决方案,并使用单个上下文实例。
I have been looking around for an answer to my question but couldn't find one, mostly because I don't really know how to phrase it!
I am playing around with EF code first and trying to implement some sort of repository pattern whilst using dependency injection (thanks to Unity). I am also trying to keep to SOLID (well, the SRP part at least) in that I have IStaffRepository
and IDepartmentRepository
interfaces which in turn implement IRepository<TEntity>
which provides basic CRUD
methods.
My question is, how can I keep to the SRP when I need to update a staff members' department?
I have read that it is bad practice to use a single DbContext
instance for all repositories due to possible memory leaks and so I cannot simply call the IDepartmentRepository
to get the new department as this would use a separate instance of my DbContext
.
The obvious solution to me is to include something like...
Department GetDepartment(int id);
Within IStaffRepository
- but would this not break the SRP?
The code I have in my Controller is...
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});
}
And the StaffMember
model contains...
public class StaffMember
{
public virtual Department Department { get; set; }
}
And the StaffViewModel
looks like this...
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;
}
}
In the database there is a int Department_ID
field which hooks up to the Department table.
I have a drop down in my view which looks like...
@Html.DropDownListFor(m => m.SelectedDepartment, Model.DepartmentList, "--Please Select--")
Apologies for the length of this question!
If all of your models are based on entities in the same database, there is not reason not to use a single context instance to manage them within the same controller. I would go with the simple solution and use a single context instance.
这篇关于如何处理不同的责任只使用一个DbContext实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!