前几天我问了这个问题:仓储层应该返回数据传输对象(DTO)吗?
答案是不应该,仓储层不应该处理DTO对象(它们的目的纯粹是为了在网络上传输),而服务层应该处理。
现在我想到了一个构造方法,需要您的意见。我的想法是,在有意义的情况下,仓储层可以返回我定义的接口类型IProjectable。它包装了查询(仓储层尚未执行查询),但不允许消费者更改查询(它不是IQueryable),只能对其执行投影操作(目前只有First和ToPagedList),执行投影并实际执行查询。
所以仓储层可能会像这样返回:
我说的正确吗?在此处执行实际数据访问仍然是存储库层的责任(应该是这样的),将其投影为可序列化形式是服务层的责任(也应该是这样的)?我唯一能想到的其他有效方法是定义一个具有所有这些属性的类型并从存储库层返回它,只是不要称其为“Dto”,因为它与DTO相同,只是为了“纯洁性”而不命名。这样看来,我大致上可以兼顾两方面。缺点是你可能会得到不匹配的结果,其中服务层执行不能实际转换为SQL的投影,这是它不必担心的,或者执行如此复杂的投影,使得实际执行数据访问的层变得成问题。顺便说一下,我正在使用Entity Framework 4。
现在我想到了一个构造方法,需要您的意见。我的想法是,在有意义的情况下,仓储层可以返回我定义的接口类型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;
我说的正确吗?在此处执行实际数据访问仍然是存储库层的责任(应该是这样的),将其投影为可序列化形式是服务层的责任(也应该是这样的)?我唯一能想到的其他有效方法是定义一个具有所有这些属性的类型并从存储库层返回它,只是不要称其为“Dto”,因为它与DTO相同,只是为了“纯洁性”而不命名。这样看来,我大致上可以兼顾两方面。缺点是你可能会得到不匹配的结果,其中服务层执行不能实际转换为SQL的投影,这是它不必担心的,或者执行如此复杂的投影,使得实际执行数据访问的层变得成问题。顺便说一下,我正在使用Entity Framework 4。