数据过滤是否发生在控制器层、服务层或存储库层?

本文关键字:服务 存储 控制器 是否 过滤 数据 | 更新日期: 2023-09-27 18:15:38

我使用ASP.NET MVC 3。我按照以下顺序获取视图的数据:

Controller -> Service Layer -> Repository

在我的存储库中,我有一个GetAll方法,用于返回特定对象(如Category)的所有记录。

如果我需要一个包含所有类别的列表那么在我的控制器中我可以这样写:

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);
}

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

数据过滤是否发生在控制器层、服务层或存储库层?

您应该尽可能从数据源中进行过滤,否则您将向上层检索记录,这些记录将由于过滤选项而被丢弃。这不能很好地扩展,因此您需要在所有需要它的层上公开过滤功能,但要确保在尽可能低的层执行实际过滤,通常是在数据库级执行。

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

既然你在使用EF,你可以利用IQueryable的延迟执行属性。检查:

。. NET实体框架- IEnumerable与IQueryable

存储库应该返回IEnumerable, IQueryable还是List?


更新:在你的评论之后,你还应该检查:

LINQ到实体和LINQ到对象-它们是一样的吗?

您应该始终尝试从数据库中获取尽可能少的数据。因此,您应该在存储库类中执行所有过滤。

许多文章建议您创建并使用通用存储库。但我认为,当应用程序增长时,它们将不能很好地工作。我建议您使用合适的搜索方法创建合适的存储库类,例如:

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

首先,您隐藏了实现细节,例如如何识别新用户。与使用泛型查询相比,它还使代码更容易理解和扩展。

你也可以添加一些过滤选项:

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

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