#c# #.net #lambda #.net-core
#c# #.net #лямбда #.net-core
Вопрос:
У меня есть метод
GetPostsByCategory
Я могу сделать это как подход A для повторного использования того, что у меня есть
A
public IEnumerable<Post> GetPostsByApartmentId(
string apartmentId,
int pageIndex,
int pageSize,
int max = 50)
{
var itemsPerPage = Math.Max(pageSize, max);
return _context.Post
.Where(p => p.ApartmentId == apartmentId amp;amp; !p.Disabled)
.Skip((pageIndex - 1) * itemsPerPage)
.Take(itemsPerPage);
}
public IEnumerable<Post> GetPostsByCategory(
string categoryId,
string apartmentId,
int pageIndex,
int pageSize,
int max = 50)
{
return GetPostsByApartmentId(apartmentId, pageIndex, pageSize, max)
.Where(p => p.CategoryId == categoryId);
}
Но меня беспокоит производительность для A,
итак, вот подход B
public IEnumerable<Post> GetPostsByCategory(
string categoryId,
string apartmentId,
int pageIndex,
int pageSize,
int max)
{
var itemsPerPage = Math.Max(pageSize, max);
return _context.Post
.Where(p => p.ApartmentId == apartmentId amp;amp; !p.Disabled amp;amp; p.CategoryId == categoryId)
.Skip((pageIndex - 1) * itemsPerPage)
.Take(itemsPerPage);
}
Однако я помню, что читал некоторые статьи, в которых говорилось: лямбда-выражение (или LINQ, не помню) на самом деле не выполняет запрос, оно просто создает запрос и выполняется только тогда, когда это необходимо, или вызывая что-то вроде ToList().
Итак, если это так, то и A, и B должны быть одинаковыми.
Может ли кто-нибудь подтвердить это, пожалуйста?
Комментарии:
1. ericlippert.com/2012/12/17/performance-rant
2. Почему вы беспокоитесь о производительности? Производительность чего именно, дополнительного вызова метода? Вы пробовали измерить разницу?
3. Похоже, вы используете Entity Framework, и возврат IEnumerable материализует результат до этого момента. Ваш актуальный вопрос «Как расширить оператор Where» ?
4. Я думаю, что если вы измените возвращаемый тип
GetPostsByApartmentId
наIQueryable<Post>
, между A и B почти не будет разницы5. Есть более важный вопрос, который вы должны задать в первую очередь: возвращает ли подход A те же результаты, что и подход B? У меня есть подозрение, что это не так. Медленный код, который выдает правильные результаты, всегда предпочтительнее быстрого кода, который выдает неправильные результаты.
Ответ №1:
Вариант B будет быстрым, поскольку он получает отфильтрованные данные за один раз.
A извлекает все данные на основе условия, а затем фильтрует на основе категории. Существует вероятность того, что в конечном итоге он может получить непреднамеренные данные.
Редактировать:
Было бы интересно в случае хранимой процедуры, как она будет себя вести.
Если у вас есть доступ к profiler, было бы легко проверить, какой оператор final SQL отправляется на sqlserver для выполнения.
Я не очень уверен во внутреннем механизме entity framework.
Но из вашего кода я думаю, что для достижения одной и той же цели компилятор / EF должен сделать что-то за сценой дважды.
Комментарии:
1. Я не думаю, что A извлекает какие-либо данные сам по себе. Он просто возвращает отложенный перечислимый. Данные извлекаются при использовании перечисляемого.
2. спасибо @TheodorZoulias за то, что я прочитал ранее, но я не могу найти ссылку, не могли бы вы, пожалуйста, помочь?
3. @Franva Я мало что знаю о Entity Framework, поэтому я не знаком с его документацией. Я хорошо знаю LINQ для объектов, который ведет себя таким образом.
4. @TheodorZoulias Речь идет о том, что выполняется в базе данных, а что выполняется локально. Подход A извлекает
itemsPerPage
элементы из базы данных, а затем дополнительно фильтрует их в памяти. Подход B выполняет фильтрацию в базе данных (и прежде чем ограничивать ееitemsPerPage
элементами).5. @Franva это называется отложенным выполнением .