Есть вот такой код вполне обычный.
Стал метод сильно тормозить. Смотрю в профайлере и вижу что идет запрос без условий, а просто
SELECT * FROM Cars
и потом получается накладывается фильтр.
То есть причина тормоза понятна. Непонятно, почему фильтр не накладывается? я думал, что до ToList\ToArray запрос собирается для базы.
Здравствуйте, merge, Вы писали:
M>Есть вот такой код вполне обычный. M>Стал метод сильно тормозить. Смотрю в профайлере и вижу что идет запрос без условий, а просто M>
M>SELECT * FROM Cars
M>и потом получается накладывается фильтр. M>То есть причина тормоза понятна. Непонятно, почему фильтр не накладывается? я думал, что до ToList\ToArray запрос собирается для базы. M>... M>И что самое интересное если сделать простой switch то работает всё шустро и в разы быстрее. M>то есть просто такой код делаем
Мне кажется, что вы не используете IQueriable в функциях CarSelectorCommon и CarSelectorLegal. Надо как-то так:
Здравствуйте, merge!
M>Стал метод сильно тормозить. Смотрю в профайлере и вижу что идет запрос без условий, а просто M>... M>И что самое интересное если сделать простой switch то работает всё шустро и в разы быстрее. M>то есть просто такой код делаем
Мне кажется, что вы не используете IQueriable в функциях CarSelectorCommon и CarSelectorLegal. Надо сделать так, чтобы они возвращали не bool, а IQueriable<Car>. Тогда SQL-запрос будет формироваться правильно.
// Здесь, скорей всего, используется перегрузка от linq2objects Func<T, bool>, а не linq2sql Expression<Func<T, bool>>var realCar = dbContext.Cars.FirstOrDefault(CarSelectorDatabase);
// Перепиши по человечески:var query = db.Cars.AsQueryable();
query = client.Type swith {
Common => query.Where(x=>...),
Legal => query.Where(x=>...),
_ => throw NotSupported()
}
return query.FirstOrDefault().ToList(); // Зачем тут, кстати, ToList(), если результат всегда один? Но это уже другой вопрос.
Здравствуйте, merge, Вы писали:
M>То есть причина тормоза понятна. Непонятно, почему фильтр не накладывается?
А почему он должен накладываться, если ты передаешь в FirstOrDefault делегат типа Func<Car,bool> ? Для IQueryable такой перегрузки FirstOrDefaultне существует. Если ты наведешь мышкой в последней строке, то выяснишь какой метод вызывается.
M>я думал, что до ToList\ToArray запрос собирается для базы.
Для IQueryable<T> так и есть.
Здравствуйте, merge, Вы писали: M>И что самое интересное если сделать простой switch то работает всё шустро и в разы быстрее.
что значит шустро? выводите на GUI? Как меряете?
Здравствуйте, merge, Вы писали: M>и потом получается накладывается фильтр. M>То есть причина тормоза понятна. Непонятно, почему фильтр не накладывается? я думал, что до ToList\ToArray запрос собирается для базы.
Всё немного сложнее. Запрос начинает выполняться в тот момент, когда вы пытаетесь обратиться к нему как к IEnumerable<T>. ToList() и ToArray() — просто два удобных способа сделать именно это.
Для того, чтобы продолжать конструирование запроса, вам нужно передавать в Where (или FirstOrDefault) не Func<T, bool>, а Expression<Func<T, bool>>.
То есть, ваш код можно было бы починить примерно так: