1

假设我有一个包含员工和部门的数据库。我创建了一个简单的对象模型来处理这个:

class Employee
{
   decimal Salary;
   Department Department;
}

class Department
{     
    decimal TotalSalaries; //calculated as the sum of all employees salaries
                           //stored in database, not just a C# property
}

和..

class Employees
{
    void Create(Employee e);
    void Update(Employee e);    
    void Delete(Employee e);
    ...
}

class Departments
{
    ...
}

如果我想更新员工,我会简单地做:

Employee emp = Employees.GetById(1);
emp.Salary += 100; //salary increase
Employees.Update(emp);

我希望每次更新其中一名员工TotalSalaries时自动重新计算DepartmentSalary

我可以执行以下操作:

void Update(Employee e)
{
     ... //
     ... // sql stuff to update employee fields.

     Departments.ReCalculateTotalSalaries(e.Department.Id);
}

但如果我这样做,我认为我违反了单一责任原则。为什么员工更新方法要关心Departments?这是一个非常简单的例子,但是如果我在实体之间有很多依赖关系,代码可能会变得非常混乱。

我已经考虑过其他方法来做到这一点:

1) 为 Employee 创建一个服务类:EmployeeService。然后在这个类中,定义一个Update()更新员工的方法。该方法将更新员工并重新计算部门总数(当然通过调用存储库方法)。

void Update(Employee e)
{
     Employees.Update(e);
     Departments.ReCalculateTotalSalaries(e.Department.Id);
}

问题:如果我的数据模型中有很多依赖项,我几乎必须将模型层“加倍”(类数 x2)。另外:我如何确定控制器(或视图)将始终调用服务方法,而不是直接调用存储库?


2)在Employees存储库中有一个事件,从方法OnSalaryChange()调用。Update()存储库Departments将订阅它并在需要时执行必要的操作(换句话说:调用ReCalculateTotalSalaries())。那么,属于什么的Departments留在DepartmentsEmployeesrepository就不用关心其他实体了。

问题:当工资发生变化时(如果有多个订阅者),可能很难理解(通过阅读代码或在调试模式下)发生了什么。如果需要按特定顺序调用订阅者,这也可能成为问题。

4

3 回答 3

1

您应该有理由在数据库中拥有一个计算字段(性能?)。我尽量避免这种情况。

原因更新不是唯一的情况:如果你删除一个员工,你也必须重新计算。

但这可能很危险(出于一个原因,您有一天在数据库中使用脚本并忘记在更新员工工资后手动更新您的部门表?)

所以

  • 你可以在你的数据库中创建一个触发器(如果你首先有代码,你总是可以使用 SMO 来保持“代码”逻辑)

  • 你可以创建一个数据库视图

  • 您可以在您的部门实体中拥有一个员工 ICollection(或 IList,或...),并以“简单获取属性”的形式获得总薪水,它将列表的薪水相加......

于 2012-04-11T21:40:51.113 回答
1

就你而言,是的,你打破了单一责任原则。

为了尊重原则,这条线

Departements.ReCalculateTotalSalaries(e.Department.Id);

应该

e.Department.ReCalculateTotalSalaries();

为此,您必须在数据库和数据库模式中使用两个实体之间的关系。

编辑:请注意,ReCalculateTotalSalaries 应该修改属性,但不应该将自身保存在数据库中。因此,因为它不接触数据库本身,所以它应该放在您的部门实体中,而不是放在您的 DepartmentRepository 中

EDIT2:当您调用时Employees.Update(yourEmployee),它还会保存 yourEmployee.Department。这就是它的魔力!无需Update()为每个实体调用一个!

于 2012-04-11T21:42:10.257 回答
-1

为什么不只是构造函数将其他存储库注入(或其他类型)到员工存储库中?

public EmployeeRepository(DepartmentRepository department){}

...然后将 _department 用于您需要的任何内容。这是一种干净的方式。您无法避免在代码中进行复杂的交互。

...或者使用一个“监督”存储库,将两者结合起来 - 并为两者注入引用 - 并且首先是 Employee 的事情,然后调用另一个?也许这更像你的想法。
MasterRepository(Employee employee, Department department)... SaveEmployee() { // 先做员工,然后... // 调用部门 }

希望这会有所帮助。

编辑:我不会参加这些事件 - 至少对于存储库来说,这是有原因的,但首先是它对 Db 和数据所在的位置感觉并不好。我不明白的第一个选项可能类似于我的主仓库。

于 2012-04-11T21:40:03.327 回答