我正在使用ASP.NET MVC 3
。我按以下顺序获取我的视图数据:
Controller -> Service Layer -> Repository
在我的存储库中,我有一个GetAll方法,它可以返回特定对象的所有记录,例如Category。
因此,如果我需要所有类别的列表,那么在我的控制器中我会有类似的东西:
IEnumerable<Category> categories = categoryService.GetAll();
在服务层我会有类似的东西:
public IEnumerable<Category> GetAll()
{
return categoryRepository.GetAll();
}
现在我需要知道我在哪里开始过滤数据?它可以在这3层中的任何一层中完成,还是只需要在存储库层中?让我们说我需要所有的父类别。我的控制器,服务层或存储库层中是否有.GetAll.Where(x => x.ParentCategoryId == null);
?
我的控制器中是否有这样的颜色:
IEnumerable<Category> categories = categoryService.GetParentCategories();
在我的服务层,我可以:
public IEnumerable<Category> GetParentCategories()
{
return categoryRepository.GetAll.Where(x => x.ParentCategoryId == null);
}
或者我的服务层必须如下所示:
public IEnumerable<Category> GetParentCategories()
{
return categoryRepository.GetParentCategories();
}
然后在我的存储库层中,像这样:
public IEnumerable<Category> GetParentCategories()
{
return GetAll()
.Where(x => x.ParentCategoryId == null);
}
请有人帮助澄清我的这种困惑。可能有不同的情况。我可能会带回所有具有活动状态的类别。我可能会带回非活动状态的类别。那我每个都需要一个方法吗?
答案 0 :(得分:4)
您应该尽可能地从数据源中过滤,否则您将检索到由于过滤选项而将被丢弃的上层的记录。这不能很好地扩展,因此您需要在需要它的所有层上公开过滤功能,但要确保实际过滤在最低层执行,通常是在数据库级别执行。
在您发布的示例中,如果使用GetAll
返回所有记录的IEnumerable
并且仅应用过滤,您将来会遇到问题,因为您基本上是在加载整个表进入内存,然后才应用过滤。
由于您使用的是EF,因此您可以利用IQueryable
的延迟执行属性。检查:
.NET Entity Framework - IEnumerable VS. IQueryable
Should a Repository return IEnumerable , IQueryable or List?
更新:跟进您的评论,您还应该检查:
答案 1 :(得分:2)
您应该始终尝试从数据库中尽可能少地获取。因此,您应该在存储库类中进行所有过滤。
许多文章都建议您创建和使用通用存储库。但是当你的应用程序增长时,它们将无法正常工作。我建议您使用适当的搜索方法创建正确的存储库类,如:
emailRepository.GetForUser("Ada");
userRepository.GetNewUsers();
首先,您隐藏了如何识别新用户的实现细节。它还使代码比使用通用查询更容易理解和扩展。
您还可以添加一些过滤选项:
emailRepository.GetForUser("Ada", Filtering.New().Paged(1, 20).SortedBy("FirstName"));
与@JoãoAngelo不同,我不建议您在存储库之外使用IQueryable
。通过这样做,您将数据库执行移动到存储库类之外。这意味着您的存储库无法处理任何错误。