没有用于检索标量值的域对象的存储库模式



最近,我努力弄清楚我的架构中的某些方法和功能是否在正确的位置;在正确的层。我想遵循 Martin Fowler 的存储库模式,将我的服务层与数据库分离。

马丁·福勒(Martin Fowler)在他的网站上解释的定义是:

存储库在域和数据映射层之间进行调解, 充当内存中域对象集合。

问题是我有很多要求,例如我必须获得所有发票的总和。如您所知,所有发票的总和是一个标量值。如果我遵循 Martin Fowler 的定义,我应该做的是创建一个函数,该函数从我的存储库层返回域对象列表,该列表由服务层接收,服务层循环抛出对象以计算总数。也有可能我不明白这种模式意味着什么的本质......

我知道在设计应用程序时性能不应该是一个问题,因为可维护性更好,但在这种情况下,在我看来,不在存储库层创建一个函数,返回一个十进制值对应于发票总数并从服务层返回相同的值,完全是在浪费开发和性能。具体化对象列表然后只使用单个属性是矫枉过正的,即使您可以使用 ORM 添加一些延迟加载策略。

存储库层返回标量值是否正确,还是我应该抵制诱惑并始终从该层返回域对象并处理服务层中的所有业务逻辑?

我也有很多地方,我的演示者直接调用我的存储库,而不是调用服务层,然后调用存储库层。这是正确的;是否可以在服务层之外调用此存储库模式?

请注意,我不想从存储库层返回 IQueryable 结果,因为这将与得墨忒耳定律完全矛盾。

另外,我不想直接在我的服务层中设置查询,因为我希望能够完全对这一层进行单元测试;而不是做集成测试。

这个问题很容易用CQRS解决(作为一个概念)。具有专用的仅查询存储库,该存储库可由 UI(或使用 MVC 时由控制器)使用。该存储库可以直接查询数据库(ORM实体并不重要)并返回您需要的内容。

仅在更新模型时保留"重"域对象和相应的存储库。

我遇到了类似的问题,最终我有一个基本和派生的存储库接口。基础将具有标准方法:获取,更新等,而派生接口将具有特定方法(在您的情况下获取标量值)。

public interface IRepository { ... }

public interface IInvoiceRepository : IRepository 
{ 
  int GetTotal(); 
}

然后,创建一个实现接口的 InvoiceRepository 类。最好在单独的类中实现业务逻辑,例如InvoiceBusinessObject,它获得IInvoiceRepository类型的依赖注入(在构造函数中使用参数)。切勿在业务层中使用实现。

public class InvoiceBusinessObject
{
  private IInvoiceRepository rep;
  public InvoiceBusinessObject(IInvoiceRepository rep)
  {
    this.rep = rep;
  }
  public int GetTotal()
  {
    return rep.GetTotal();
  }
}

服务层可以实例化 InvoiceRepository 类并将实例注入到业务对象类中:

public int GetTotalFromService()
{
  IInvoiceRepository rep = new InvoiceRepository();
  InvoiceBusinessObject bizObj = new InvoiceBusinessObject(rep);
  return bizObj.GetTotal();
}

最新更新