Происходит ли фильтрация данных на уровнях контроллера, службы или хранилища? - PullRequest
7 голосов
/ 25 ноября 2011

Я использую 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();

А в слое обслуживания я могуhave:

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

ПожалуйстаМожет кто-нибудь помочь прояснить эту путаницу, которая у меня есть.Там могут быть разные сценарии.Я мог бы вернуть все категории, которые имеют активный статус.Я мог бы вернуть категории с неактивным статусом.Тогда мне нужен метод для каждого?

Ответы [ 2 ]

5 голосов
/ 25 ноября 2011

Вы должны фильтровать как можно ближе к источнику данных, в противном случае вы будете извлекать записи на верхние уровни, которые будут просто отброшены из-за опции фильтрации.Это плохо масштабируется, поэтому вам необходимо предоставить возможности фильтрации на всех уровнях, которые в этом нуждаются, но убедитесь, что фактическая фильтрация выполняется на самом низком уровне, как правило, на уровне базы данных.

Inпример, который вы опубликовали, если использовать GetAll, который возвращает IEnumerable всех записей и только затем применяет фильтрацию, у вас будут проблемы в будущем, потому что вы в основном загружаете всю таблицу в память и только затем применяете фильтрацию.

Поскольку вы используете EF, вы можете воспользоваться свойствами отложенного выполнения IQueryable.Проверьте:

.NET Entity Framework - IEnumerable VS.IQueryable

Должен ли репозиторий возвращать IEnumerable, IQueryable или List?


Обновление: В продолжение вашего комментария вы должнытакже проверьте:

LINQ для объектов против LINQ для объектов - они одинаковы?

2 голосов
/ 25 ноября 2011

Вы всегда должны пытаться получить как можно меньше из базы данных.И поэтому вы должны выполнять всю фильтрацию в своих классах репозитория.

Во многих статьях предлагается создавать и использовать универсальные репозитории.Но imho они не будут работать очень хорошо, когда ваше приложение будет расти.Я рекомендую вам создавать надлежащие классы репозитория с соответствующими методами поиска, такими как:

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

Прежде всего, вы скрываете детали реализации, например, как идентифицировать новых пользователей.Это также облегчает понимание и расширение кода, чем использование универсального запроса.

Вы также можете добавить некоторые параметры фильтрации:

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

В отличие от @ JoãoAngelo, я НЕ рекомендую использовать IQueryable за пределами вашего хранилища.Тем самым вы переместите выполнение базы данных за пределы вашего класса репозитория.А это значит, что никакие ошибки не могут быть обработаны вашим хранилищем.

...