DDD Auditing? Domain Layer or Repository Layer?

use*_*367 5 design-patterns domain-driven-design repository-pattern

The application i'm currently working on requires every made to the database be audited in another table:

ex: Employee Table has EmployeeAuditTable

I've been debating on where i should put the auditing functionality! Following DDD could anyone offer me their advice and opinion.

The options that come to mind to me are the following 1.) When a "Repository" calls save changes, i should perform the auditing logic from the repository ( Is this bad design/practice to have the Repository not only persist changes but also persist Auditing details as well? Is it even good practice to have a service being called from within a repository( IAuditService in this case ) )

Example 1:

public class EmployeeRepository : IRepository
{
    DbContext _db;
    IAuditService _auditService;

    EmployeeRepository(IAuditService auditService)
    {
      _auditService = auditService
    }
    void Update(Employee empl)
    {
        // Update Employee with dbcontext entity framework

        // Perform Audit using AuditService
    }

   void SaveChanges()
   {
      // Call save changes on dbcontext
   }

}
Run Code Online (Sandbox Code Playgroud)

2.) Should i call IAuditService within my application services

Example 2:

public class EmployeeService
{
   IAuditService _auditService;
   IUnitOfWork   _unitOfWork;
   IEmployeeRepository _repository;

   EmployeeService(IAuditService auditService, IUnitOfWork  unitOfWork, IEmployeeRepository repo)
   {
       _auditService = auditService;
       _unitOfWork= unitOfWork;
       _repo  = repo;
   }

   void UpdateEmployee(int id, string name, int age)
   {
      // Get Employee

      // Update Employee

      // Audit Changes

      // Commit Transaction

   }


}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ijn 5

我知道您希望对数据库中的所有对象进行审计跟踪,但我不会监督您问题的全部复杂性。不太清楚你Employee和你的EmployeeAuditTable样子,但选择的命名约定表明它包含与员工表相同的列。

审计可以并且经常被认为是一个“交叉关注点”。当您有诸如“应审核所有更改”之类的要求时,尤其如此。如果审计是不是企业关注的(或用例或者无论你怎么称呼它),你应该不要把它放在你的实体,服务或信息库; 如果仅仅是因为在审计中忘记编码非常非常容易,给您留下不正确的审计跟踪——有些人认为这比根本没有审计跟踪更糟糕。

形成您的代码示例,我看到您正在使用一个工作单元。我想象在

// commit transaction
Run Code Online (Sandbox Code Playgroud)

您提交工作单元跟踪的更改:

// commit transaction
_unitOfWork.Commit();
Run Code Online (Sandbox Code Playgroud)

同样,它提交由工作单元跟踪的更改。这是您的审计挂钩点,它不需要在您的任何服务、实体或存储库中进行编码。

事实上,当你使用像 (N)Hibernate 这样的 ORM 框架时,你可以让 ORM 为你跟踪更改(它会为此挂钩到它的工作单元中),例如参见维基页面“创建审计使用事件记录”或NHibernate的Envers审计框架,也在这个关于 SO 的答案中讨论过。我强烈建议您阅读 Envers 文档,即使您实施自己的审计解决方案。