我的服务和存储层的职责
Posted
技术标签:
【中文标题】我的服务和存储层的职责【英文标题】:The responsibilities of my service and repository layer 【发布时间】:2011-07-12 21:45:36 【问题描述】:前几天我问了这个问题:
Should the repository layer return data-transfer-objects (DTO)?
答案(只有一个人,但我已经预感到这不是一个好主意)是不,以后的存储库不应该处理 DTO 对象(它们的目的纯粹是为了通过网络发送),服务层应该处理这个问题。
现在我想出了一个结构,同时我需要你的意见。这个想法是,当这样做有意义时,存储库层可以返回我定义的名为IProjectable
的接口类型。这包装了查询(存储库层尚未执行查询)但不允许消费者更改查询(不是IQueryable
),只是为了对其执行投影操作(到目前为止对我来说只有First
和ToPagedList
) 将执行投影并实际执行查询。
所以在存储库中是这样的:
public IProjectable<User> GetUser(int id)
var query = from u in Set<User>()
where u.UserID == id
select u;
return query.AsProjectable();
在服务层是这样的:
var dto = repository.GetUser(16).Single(u => new SimpleUserDto
FullName = u.FirstName + " " + u.LastName,
DisplayAddress = u.Address.Street + u.Address.HouseNumber,
OrderCount = u.Orders.Count()
);
return dto;
我是否正确地说在这里进行实际数据访问仍然是存储库层的责任(应该是),而对可序列化表单的投影是服务层的责任(应该是) ?
我看到的唯一其他方法有效地(从存储库返回User
并在服务层中对他的Orders
执行Count()
会导致额外的查询到数据库)是定义一个具有所有这些属性的类型并从存储库层返回它,只是不要称它为“Dto”,这看起来很愚蠢,因为它与 DTO 相同,只是名称不同为了“纯洁”。这样一来,我似乎也可以大部分时间吃蛋糕了。
我看到的缺点是,您可能会在服务层执行的预测不匹配,而这些预测实际上不能被转换为它不应该必须担心的 SQL,或者它在哪里执行如此复杂的预测让人怀疑是哪一层在进行实际的数据访问。
顺便说一句,如果重要的话,我正在使用 Entity Framework 4。
【问题讨论】:
【参考方案1】:我说的是否正确 这里的实际数据访问仍然是 存储层的职责 (应该如此)并且 投影到可序列化的形式是 服务的责任 层(应该是)?
是的,服务层仍然不知道实际的 DataAccess 是如何执行的(因为它不应该不知道)。调用是否发送到 SQL?中间有缓存层吗?
我看到的缺点是你可以得到 服务层不匹配 执行无法执行的预测 实际上被翻译成它的 SQL 不必担心,或者 它执行如此复杂的地方 令人怀疑的预测 什么层在做实际数据 访问。
对于这个问题,我使用了一种管道模式,它基本上只是 IProjectable 上的一组扩展方法,可以执行经过测试的投影。接下来,在您的 serviceLayer 中,您可以使用这些管道方法的组合来编写查询,例如:
var users = repository.GetUsers().FilterByName("Polity").OrderByAge().ToTransferObjects();
【讨论】:
【参考方案2】:我最尊敬的开发者之一ayende (http://ayende.com/Blog/Default.aspx) 说:“ORM 是你的存储库”视频在这里 -> http://community.devexpress.com/blogs/seth/archive/2011/03/09/interview-with-ayende-rahien-aka-oren-eini.aspx
问题是你真的需要存储库模式吗? 只是我的意见:)
【讨论】:
存储库模式实际上仍然非常有用,即使在使用 ORM 框架时也是如此。例如,尽管使用了 LinqToSql,但我肯定需要存储库模式。那是因为我有一个实际使用数据库的“真实”存储库实现和一个仅用于单元测试的假存储库实现。虽然可以使用模拟来代替,但对于大量测试来说太乏味了(现在我有大约 900 个测试,其中大多数有几个不同的断言)。 @Adrian Grigore - 好点,与所有模式一样,不要自动使用它们。你知道很多人不知道你使用存储库的方式。那是可能的点。以上是关于我的服务和存储层的职责的主要内容,如果未能解决你的问题,请参考以下文章