【发布时间】: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。
【问题讨论】:
标签: c# entity-framework entity repository-pattern service-layer