Architecture 访问存储库的域实体

Architecture 访问存储库的域实体,architecture,domain-driven-design,repository-pattern,ddd-repositories,Architecture,Domain Driven Design,Repository Pattern,Ddd Repositories,继续这些辩论: 在某些情况下,域访问存储库感觉更好。以本例为例,假设数据库中需要一个TaskStatus表,其中包含用于报告目的的说明: 公共类任务状态 { 公共长Id{get;set;} 公共字符串说明{get;set;} } 公开课任务 { 公共长Id{get;set;} 公共字符串说明{get;set;} 公共任务状态状态{get;set;} 公共void CompleteTask() { ITaskStatusReposity repository=ObjectFactory.Get

继续这些辩论:

在某些情况下,域访问存储库感觉更好。以本例为例,假设数据库中需要一个TaskStatus表,其中包含用于报告目的的说明:

公共类任务状态
{
公共长Id{get;set;}
公共字符串说明{get;set;}
}
公开课任务
{
公共长Id{get;set;}
公共字符串说明{get;set;}
公共任务状态状态{get;set;}
公共void CompleteTask()
{
ITaskStatusReposity repository=ObjectFactory.GetInstance();//或您执行的任何操作。
Status=repository.LoadById(Constants.CompletedTaskStatusId);
}
}
我知道我可以拥有CompletedTaskStatus和OpenTaskStatus对象,但在某些情况下,这是不必要的,可能会导致类爆炸


无论如何,如果不是为了这类事情,为什么存储库接口存储在域中?

实体可以访问存储库吗

不,请不要这样做

首先,域模型的思想是将业务逻辑从应用程序中分离出来。将其与数据库、存储库和应用程序隔离。这允许您将业务逻辑保持独立,并允许将其测试和更改与应用程序分开

域应该完全不知道数据持久性,并且应该假设它是自动发生的

其次,还有其他更实际的理由不将存储库注入实体

  • 您的实体应该是可单元测试的,通过将存储库注入到您的实体中,您已经在存储库上创建了一个依赖项

  • 使用GetInstance()方法打破了Demeter定律,您正在创建ITaskStatusRepository与实体的紧密耦合。这意味着,在创建新任务和编写单元测试时,任务需要ITaskStatusRepository这一点并不明显。这使得对业务逻辑进行单元测试变得更加困难

  • 从DDD的角度来看,存储库不仅与数据库接口有关,还可以从内存存储中检索。或者一份清单

  • 您的存储库不必与表保持1对1的关系。如果需要任务存储库执行与其他表的内部联接以执行复杂查询,并且它返回任务项列表,则可以从存储库中公开执行该查询的方法。(我认为这是对存储库模式的常见误解)

  • 您的实体不应该关心在db上执行操作

  • 请参阅此处发布的图片:

    在应用程序层内部,您的存储库负责(或不负责)持久性。存储库是聚合根的列表。它在聚合根级别工作

    在TaskService中使用任务的示例。服务作用于来自应用层的实体

    public class TaskService 
    {
        private readonly ITaskRepository _taskRepository;
    
        public TaskService(ItaskRepository taskRepository){
          _taskRepository = taskRepository;
        }
    
        public List<Task> CompleteAllTasks()
        {
          List<Tasks> getTasks = _taskRepository.GetTasks();
          getTasks.ForEach(CompleteTask);
          return _taskRepository.Save(getTasks);
        }    
    }
    
    公共类任务服务
    {
    专用只读ITaskRepository\u taskRepository;
    公共任务服务(ItaskRepository任务存储库){
    _taskRepository=taskRepository;
    }
    公共列表CompleteAllTasks()
    {
    List getTasks=_taskRepository.getTasks();
    gettask.ForEach(CompleteTask);
    返回_taskRepository.Save(getTasks);
    }    
    }
    
    1+2:通过访问ITaskStatusRepository,域不知道持久性的本质,尽管我承认它知道持久性的存在。当然它仍然是单元可测试的,因为存储库可以模拟出来?我仍然不确定您建议我如何实现上述目标?3:我不确定我的存储库除了访问数据库之外还做了什么?4:好的,那么TaskStatus可以是一个枚举,您可以有类似于“public void Complete(){Status=TaskStatus.Complete;}”的内容,并且StatusDescription应该是Task的属性?除非我弄错了,否则我不会真正接受“CompleteTask”是属于存储库的内容。我的示例非常简单,唯一的业务逻辑是当任务完成时,其状态更改为“已完成”。这个逻辑可能要复杂得多,当然不应该在存储库中完成?使用您的新编辑,我无法再从任务中访问任务状态的描述?
    public class TaskService 
    {
        private readonly ITaskRepository _taskRepository;
    
        public TaskService(ItaskRepository taskRepository){
          _taskRepository = taskRepository;
        }
    
        public List<Task> CompleteAllTasks()
        {
          List<Tasks> getTasks = _taskRepository.GetTasks();
          getTasks.ForEach(CompleteTask);
          return _taskRepository.Save(getTasks);
        }    
    }