6

我正在使用ASP.NET MVC 3。我得到我的观点的数据按以下顺序:是否在控制器,服务或存储库层中进行数据过滤?

Controller -> Service Layer -> Repository 

在我的仓库我有一个GETALL方法带回的所有记录特定对象,如类别。

所以,如果我需要的所有类别的名单,然后在我的控制器我会是这样的:

IEnumerable<Category> categories = categoryService.GetAll(); 

在服务层我想有这样的事情:

public IEnumerable<Category> GetAll() 
{ 
    return categoryRepository.GetAll(); 
} 

现在这是我需要知道的,我在哪里开始过滤数据?它可以在这三个层中的任何一层中的任何位置完成,还是只能位于存储库层?可以说我需要所有父类别。我的控制器,服务层或存储库层中是否有.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); 
} 

请有人帮助澄清我有这种困惑。可能有不同的情况。我可能会带回所有具有活动状态的类别。我可能会带回处于非活动状态的类别。那我是否需要每个方法?

回答

4

您应该尽量过滤数据源,否则您会将记录检索到上层,由于过滤选项而只会丢弃上层。这不能很好地扩展,所以你需要在所有需要它的层上公开过滤功能,但是要确保实际的过滤是在尽可能低的层次上执行的,通常它是在数据库级执行的。

在您发布的示例中,如果使用GetAll返回所有记录的IEnumerable,然后应用筛选,您将来会遇到问题,因为基本上是将整个表加载到内存中,然后才应用过滤。

由于您使用的是EF,因此您可以利用IQueryable的延期执行属性。检查:

.NET Entity Framework - IEnumerable VS. IQueryable

Should a Repository return IEnumerable , IQueryable or List?


更新:跟进您的评论,你还应该检查:

LINQ to entities vs LINQ to objects - Are they the same?

+0

GetAll只是一个示例方法,主要关注于过滤部分。然后我是否在储存库中为每个用途创建一个方法?但是.Where(...)的工作方式不像使用where子句的sql select? –

+0

只有当你使用LINQ to实体时,你需要一个'IQueryable'。 –

+0

是的。我有一个方法获取 tat在存储库中是IQueryable,因此存储库可以处理所有条件。一个GetALlUsers()方法让我开火。像地狱一样效率低下。吸引100.9000用户获得名称 - 不。 – TomTom

2

你应该尽量少取尽可能从数据库中获取。因此,您应该在存储库类中进行所有过滤。

许多文章都建议您创建并使用通用存储库。但是,当你的应用程序增长时,它们不能很好地工作。我建议你创建正确的存储库类与像适当的搜索方法:

emailRepository.GetForUser("Ada"); 
userRepository.GetNewUsers(); 

首先,你隐藏比如如何识别新用户实现细节。与使用通用查询相比,它还使代码更易于理解和扩展。

您还可以添加一些过滤选项:

emailRepository.GetForUser("Ada", Filtering.New().Paged(1, 20).SortedBy("FirstName")); 

不像@JoãoAngelo我不建议您使用IQueryable外面你的资料库。通过这样做,您可以将数据库执行移到仓库类之外。这意味着任何错误都无法由您的存储库处理。

相关问题