前几天我问了这个问题:
答案(只有一个人,但我已经预感到这不是一个好主意)是不,存储库以后不应该处理 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
从存储库返回 a并在服务层中Count()
对他执行Orders
将导致对数据库的额外查询)是定义一个具有所有这些属性的类型并从存储库层,只是不要称它为“Dto”,这看起来很愚蠢,因为它与 DTO 相同,只是为了“纯度”而没有命名相同。这样一来,我似乎也可以大部分时间吃蛋糕了。
我看到的缺点是,您可能会得到一个不匹配的地方,服务层执行的预测实际上无法转换为它不应该担心的 SQL,或者它执行如此复杂的预测,这使得它是什么层是有问题的进行实际的数据访问。
顺便说一句,如果重要的话,我正在使用 Entity Framework 4。