c# - 存储库模式以及如何管理实体之间的依赖关系

标签 c# database repository design-patterns

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

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);

我希望每次更新其中一名员工的 Salary 时自动重新计算 DepartmentTotalSalaries

我可以做以下事情:

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)。另外:我如何确定 Controller (或 View )将始终调用服务方法,而不是直接调用存储库?


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

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

最佳答案

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

因为更新不是唯一的情况:如果您删除了一个 Employee,您也必须重新计算。

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

所以

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

  • 您可以创建数据库 View

  • 您可以在您的 Department 实体中拥有一个 Employees ICollection(或 IList,或...),并以“简单获取属性”的形式获得总薪水,它对列表的薪水求和...

关于c# - 存储库模式以及如何管理实体之间的依赖关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10114264/

相关文章:

c# - PostAsJsonAsync 可以抛出哪些异常?

c# - Sqlite.NET 不知道 int[]?

database - 如何在 Laravel 5 中配置 MariaDB?

c# - 自动属性验证

c# - 错误 1001。指定的服务已经存在。无法删除现有服务

c++ - PQexecparams - 不支持绑定(bind)数组中的第三个参数

VPS 上的 Git 远程存储库接受推送但不创建文件?

git - 识别标签属于git中的哪个分支

mysql - 我在查询生成器 SYMFONY 中遇到问题

c# - 如何将顺序打印语句与嵌套 for 循环分开?