C# 我的服务和存储库层的职责

C# 我的服务和存储库层的职责,c#,entity-framework,entity,repository-pattern,service-layer,C#,Entity Framework,Entity,Repository Pattern,Service Layer,前几天我问了这个问题: 答案是不,存储库以后不应该处理DTO对象(它们的目的纯粹是通过线路发送),服务层应该处理这个问题 现在我提出了一个结构,同时我需要你的意见。其思想是,当这样做有意义时,存储库层可以返回我定义的接口类型,称为IProjectable。这会包装查询(存储库层尚未执行查询),但不允许使用者更改查询(它不是IQueryable),只是对其执行投影操作(到目前为止,仅限我首先执行投影并实际执行查询的和ToPagedList) 所以在存储库中类似这样的内容: public IPro

前几天我问了这个问题:

答案是不,存储库以后不应该处理DTO对象(它们的目的纯粹是通过线路发送),服务层应该处理这个问题

现在我提出了一个结构,同时我需要你的意见。其思想是,当这样做有意义时,存储库层可以返回我定义的接口类型,称为
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;