考虑下面的简化示例:

public class Ticket
{
   public int Id;
   public TicketState State;

   public Ticket()
   {
      // from where do I get the "New" state entity here? with its id and name
      State = State.New;
   }

   public void Finished()
   {
      // from where do I get the "Finished" state entity here? with its id and name
      State = State.Finished;
   }
}

public class TicketState
{
   public int Id;
   public string Name;
}

类状态直接在域对象票证中使用。在票证的生命周期的后期,可能会设置其他状态。

工单将保留在工单表以及工单状态中。因此,在数据库中,票证将具有到票证状态表的外键。

在我的实体中设置适当的状态时,如何从数据库中加载状态实例?我是否必须将存储库注入(inject)实体?在这种情况下,我是否需要使用像城堡之类的框架?还是有更好的解决方案,也许是从外部传递状态?
public class Ticket
{
   //...
   public ITicketStateRepository stateRep; //<-- inject

   public Ticket()
   {
      State = stateRep.GetById(NEW_STATE_ID);
   }
   //...
}

有什么最佳实践吗?到目前为止,我没有使用任何依赖注入(inject)框架或任何东西,并且将任何持久性东西都排除在我的范围之外。

另一个方法:
public class Ticket
{
   //...

   public Ticket(NewTicketState newTicketState)
   {
      State = newTicketState;
   }
   public void Finished(FinishedTicketState finishedTicketState)
   {
      State = finishedTicketState;
   }
   //...
}

最佳答案

工单将没有对存储库的引用。它与TicketState具有一对一的关系,而TicketRepository只需执行JOIN并将值映射到Ticket中。

当我创建模型对象时,我通常不让他们知道它们是否是持久性的,因此不会向它们注入(inject)存储库。该存储库处理所有CRUD操作。

有人对此表示反对,说这导致了anemic domain model;也许你是其中之一。如果是这种情况,请将存储库注入(inject)到Ticket对象中,但是只需简单地要求它执行JOIN并返回填充了状态的Ticket。插入或更新时,必须将两个表修改为一个工作单元,因此请确保已打开事务。

我喜欢在域模型对象之外使用CRUD ops的原因是,它通常不是参与用例或事务的唯一域对象。例如,也许您简单的“购买机票”用例将具有一个“机票”对象,但是可能还必须有一些其他对象来处理预订和座位,总分类帐和行李 list 以及其他各种事项。您确实要将几个模型对象作为单个工作单元来保留。只有服务层才能知道何时模型对象自己发挥作用以及何时成为更大,更宏大计划的一部分。

更新:

我不喜欢用DAO注入(inject)模型对象以便它可以处理持久性任务的另一个原因是对层的破坏和引入的循环依赖关系。如果保持模型对任何对持久性类的引用都不受影响,则可以使用它们而不必调用另一层。这是一种单向依赖;持久性了解模型,但是模型不了解持久性。

将持久性注入(inject)模型中,它们便会周期性地相互依赖。您不能在没有另一个的情况下使用或测试任何一个。没有分层,没有关注点分离。

10-02 01:15
查看更多