编写从存储库中检索数据的服务层方法的最佳做法是什么?
假设我们有两个模型:Team
和User
(用户是团队的一员):
public class User {
public int Id { get; set; }
public string Name { get; set; }
public int TeamId { get; set; }
public virtual Team Team { get; set; }
public bool Active { get; set; }
}
public class Team {
public int Id { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
}
如果我想编写服务以通过各种条件从存储库中检索用户数据,我是否必须编写多种方法来获取用户,例如getAll
,getAllByName
,getAllActiveByName
,getAllActiveByTeamId
,getAllActiveByNameAndTeamId
等?
public IEnumerable<User> GetAll()
{
return _repository.GetAll();
}
public IEnumerable<User> GetAllActiveByName(string name)
{
return _repository.GetBy(u => u.Name == name && u.Active);
}
public IEnumerable<User> GetAllActiveByNameAndTeamId(string name, int teamId)
{
return _repository.GetBy(u => u.Name == name && u.Active && u.TeamId == teamId);
}
这些只是简单的例子,但在现实生活中,当模型更复杂时,我们最终可能会为不同的场景提供数十种服务方法。
或者最好让一个GetBy
方法根据提供的过滤器返回用户?我使用Generic Repository Pattern,我可以在实现GetBy服务方法时使用GetBy方法:
public IEnumerable<User> GetBy(Expression<Func<User, object>>filter )
{
return _usersRepository.GetBy(filter);
}
有了这个,我不必为所有场景编写数十个“重复”方法。 然后设置过滤器是控制器的责任:
public ViewResult Index(int teamId = 0){
//[...]
var users = _usersService.GetBy(u => u.IsActive && u.teamId == teamId);
//[...]
}
对此有何看法?
答案 0 :(得分:1)
我认为您应该拥有与场景一样多的查询方法。
通过这种方式,您可以通过例如使用预先计算的视图来优化单个查询。 您的某些查询可能会使用预先加载,其他人可能会使用延迟加载...
另外,如果您总是返回IQueryable
,您将如何测试它?您的服务只有一个方法GetAll
并且非常贫乏,您可以直接删除它并直接在控制器中使用存储库。
针对GetAll
的另一个论点是,任何人都可以在UI中执行任何查询!
考虑阅读CQRS。
答案 1 :(得分:0)
或者最好只使用一个只返回的getAll方法 活跃用户,然后在控制器中使用lambda表达式?
没有。这种查询仅适用于内存过多的静态数据。假设您有一些应用程序级数据并且它不会在一定时间内更改,那么不是每次都查询它,而是首次获取然后放入本地服务器缓存。然后将其用于下一个同时请求。但是这种方法不适用于大量改变动态数据。此查询的性能也取决于它返回的记录数,因此有时可能会产生非常糟糕的性能。
我是否必须编写多种方法来获取用户,例如得到所有, getAllByName,getAllActiveByName,getAllActiveByTeamId, getAllActiveByNameAndTeamId等?
好多了。这种方法可以为您提供按需加载,即在需要时加载必要的数据,而不是获取所有数据并将其丢弃。