我正在使用nHibernate编写ASP.Net webforms应用程序。目前我没有使用任何IoC框架。
首先 - 我的情景:
我不想允许两个同名的员工。我想启用Employee类来搜索具有相同名称的其他Employee并发出错误。
一个部门可能有1000名员工。我需要确切知道每个部门有多少员工。我不想将它们全部加载到内存中,因此我使用计算属性 - EmployeesCount。但是,第一次加载Department对象时会初始化此属性。如果我添加/删除员工,则更改不会反映在该属性中。 (特别是因为我正在使用二级缓存,因此我的对象会持续存在多个会话范围)
我解决这些问题的想法是让我的域对象保持对相应Repository对象的引用 我认为最好的解决方案是让我的存储库实现接口并使用某种IoC容器/ DI机制。
所以,在员工中我会:
if (_empRepository.GetEmployeeByName(newEmployeeName) != null) //...
和部门:
public int EmployeesCount
{
get
{
return _departmentRepository.GetCurrentEmployeesCount(this);
}
}
我的问题:
这是令人难以忍受的 - 来自DI
公共员工(IEmployeeRepository存储库)
或使用IoC容器?
public Employee()
{
_empRepository = container.Resolve<IEmployeeRepository>();
}
答案 0 :(得分:4)
POC0到持久性关系通常是单向的:持久层知道POCO,但不是相反。
当你让POCO负责搜索同名的其他员工之类的那一刻,你就会把它变成双向的。我会担心你的设计中模块之间的周期增长。
将这项活动纳入POCO可能听起来不错,因为它有助于避免“贫血领域模型”标签,但我不会这样做。我将这些方法放在持久性接口上,让它们处理它。负责完成用例的服务也更有可能想知道重复的员工姓名;让它做出询问,让POCO离开谈话。
这种方法将使您的测试生活更轻松。你会知道进行测试时模块周期会有多痛苦。你必须将太多的机器拖入测试才能使它发挥作用。
答案 1 :(得分:3)
我也认为Pocos不应该知道持久性。您是否考虑过
等替代方案class Department
{
public int Id { get; set; }
public IList<Employee> ActiveEmployees { get; set; }
}
public DepartmentMap()
{
...
HasMany(d => d.ActiveEmployees)
.KeyColumn("department_id")
.Where("stillactiveindepartment = true") // for example
.ExtraLazyLoad(); // will issue an Count(*) instead of initializing collection, also other methods like Contains() issue an sql
}
对于具有唯一名称的员工:
1)在service / controler中:在保存新员工之前,发出一个查询,检查是否已存在同名员工。
2)数据库中的唯一约束将在保存时提供异常。
3)会话中的自定义拦截器,它挂接了save / flush事件。如果已经有客户,它可以抛出
答案 2 :(得分:1)
另一个答案主要是针对你提出的问题,我同意那里的建议。
有关访问员工计数的问题,请查看使用NHibernate的投影。我会在您的服务层(用于获取员工数量的任何Web服务操作)中使用计数投影进行查询。
编辑:忘了你正在使用服务/存储库/ POCO。在这种情况下,在存储库中创建一个员工计数查询,并从服务中调用它。