最近,我努力想弄清楚我的架构中的某些方法,功能是否处于好的位置;在正确的层。我想按照the repository pattern of Martin Fowler将我的服务层与数据库分离。
Martin Fowler在他的网站上解释的定义说:
存储库在域和数据映射层之间进行调解, 表现得像内存中的域对象集合。
问题在于我有很多要求,例如我必须得到所有发票的总和。如您所知,所有发票的总和是标量值。如果我遵循Martin Fowler的定义,我应该做的是创建一个函数,该函数返回我的存储库层中的域对象列表,该列表由服务层接收,循环抛出对象以计算总计。我也可能不理解这种模式的本质......
我知道在设计应用程序时性能不应该是一个问题,因为可维护性更好,但在这种情况下,我认为在开发和性能方面完全浪费时间不创建功能在存储库层中,返回与发票总数相对应的十进制值,并从服务层返回相同的值。即使您可以使用ORM添加一些延迟加载策略,实现对象列表然后只使用单个属性也是一种过度杀伤。
从存储库层返回标量值是否正确,或者我是否应该抵制诱惑并始终从此层返回域对象并处理服务层中的所有业务逻辑?
我还有很多地方,我的演示者直接调用我的存储库,而不是调用服务层,然后调用存储库层。它是正确的;可以接受在服务层之外调用此存储库模式吗?
请注意,我不想从我的存储库层返回IQueryable结果,因为这与Law of Demeter完全矛盾。
另外,我不想直接在我的服务层设置查询,因为我希望能够完全对该层进行单元测试;没有进行集成测试。
答案 0 :(得分:2)
使用CQRS(作为概念)可以轻松解决问题。有一个专门的查询存储库,可以由UI(或使用MVC时由控制器)使用。该repo可以直接查询db(它并不重要的ORM实体)并返回您需要的内容。
仅在更新模型时保留“重”域对象和相应的存储库。
答案 1 :(得分:1)
我有类似的问题,我最终得到了一个基础和派生的存储库接口。基础将具有标准方法:获取,更新等,而派生接口将具有特定方法(在您的情况下获取标量值)。
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();
}