C# 我的服务和存储库层的职责
前几天我问了这个问题: 答案是不,存储库以后不应该处理DTO对象(它们的目的纯粹是通过线路发送),服务层应该处理这个问题 现在我提出了一个结构,同时我需要你的意见。其思想是,当这样做有意义时,存储库层可以返回我定义的接口类型,称为C# 我的服务和存储库层的职责,c#,entity-framework,entity,repository-pattern,service-layer,C#,Entity Framework,Entity,Repository Pattern,Service Layer,前几天我问了这个问题: 答案是不,存储库以后不应该处理DTO对象(它们的目的纯粹是通过线路发送),服务层应该处理这个问题 现在我提出了一个结构,同时我需要你的意见。其思想是,当这样做有意义时,存储库层可以返回我定义的接口类型,称为IProjectable。这会包装查询(存储库层尚未执行查询),但不允许使用者更改查询(它不是IQueryable),只是对其执行投影操作(到目前为止,仅限我首先执行投影并实际执行查询的和ToPagedList) 所以在存储库中类似这样的内容: public IPro
IProjectable
。这会包装查询(存储库层尚未执行查询),但不允许使用者更改查询(它不是IQueryable
),只是对其执行投影操作(到目前为止,仅限我首先执行投影并实际执行查询的和ToPagedList
)
所以在存储库中类似这样的内容:
public IProjectable<User> GetUser(int id)
{
var query = from u in Set<User>()
where u.UserID == id
select u;
return query.AsProjectable();
}
我说在这里进行实际的数据访问仍然是存储库层的责任(应该是这样),而向可序列化形式的投影是服务层的责任(应该是这样)是正确的吗
我认为有效地执行此操作的唯一其他方法(从存储库返回用户
,并在服务层对其订单
执行计数()
,将导致对数据库的额外查询)是定义一个具有所有这些属性的类型,然后从存储库层返回,而不调用它“Dto”,看起来很傻,因为它与Dto完全相同,只是为了“纯洁”而没有命名相同的Dto。这样,看起来,我可以吃我的蛋糕,并且大部分时间都可以吃
我看到的缺点是,服务层执行的投影实际上无法转换为SQL,这一点不必担心,或者服务层执行的投影非常复杂,这使得实际数据访问的层有问题
顺便说一下,我使用的是实体框架4,如果有必要的话
我这样说对吗
这里的实际数据访问仍然是
存储库层的职责
(应如此)以及
向可序列化形式的投影是
服务的责任
图层(应该是这样的)
是的,服务层仍然不知道实际的数据访问是如何执行的(因为它不应该知道)。调用是否发送到SQL?中间是否有缓存层
我看到的缺点是你可以
服务层不匹配
执行无法执行的投影
实际上,它可以被转换为SQL
不必担心,或者
它在哪里执行如此复杂的任务
让人怀疑的预测
哪一层在处理实际数据
进入
对于这个问题,我使用管道模式,它基本上只是IProjectable上的一组扩展方法,可以执行测试的投影。接下来,在serviceLayer中,您可以使用这些管道方法的组合编写查询,例如:
var users=repository.GetUsers().FilterByName(“Polity”).OrderByAge().ToTransferObjects();我最尊敬的开发者之一(http://ayende.com/Blog/Default.aspx)说:“ORM是你的存储库”视频在这里->
问题是您真的需要存储库模式吗?
仅凭我的观点:)存储库模式实际上仍然非常有用,即使在使用ORM框架时也是如此。例如,尽管使用了LinqToSql,但我确实需要存储库模式。这是因为我有一个“真正的“实际使用数据库的存储库实现和仅用于单元测试的伪数据库。虽然可以使用mock,但是对于大量的测试来说,这太单调了(现在我有大约900个测试,其中大多数都有几个不同的断言)。@Adrian Grigore-很好的一点,就像所有模式一样,不要自动使用它们。你们知道你们使用存储库的方式,但很多人不知道。这就是梅的观点。
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;