Я использую NHibernate 3.2, и у меня есть метод репозитория, который выглядит следующим образом:
public IEnumerable<MyModel> GetActiveMyModel()
{
return from m in Session.Query<MyModel>()
where m.Active == true
select m;
}
Который работает как положено. Однако иногда, когда я использую этот метод, я хочу отфильтровать его дальше:
var models = MyRepository.GetActiveMyModel();
var filtered = from m in models
where m.ID < 100
select new { m.Name };
Который выдает тот же SQL, что и первый, а второй фильтр и выбор должны быть выполнены после факта. Я думал, что весь смысл в LINQ состоит в том, что он сформировал дерево выражений, которое было развернуто, когда это было необходимо, и поэтому можно было создать правильный SQL для задания, сохранив мои запросы к базе данных.
Если нет, то это означает, что все мои методы репозитория должны возвращать именно то, что нужно, и я не могу использовать LINQ дальше по цепочке без штрафов.
Я правильно понял?
Обновлено
В ответ на комментарий ниже: я пропустил строку, в которой я повторяю результаты, что приводит к запуску исходного SQL (WHERE Active = 1), а второй фильтр (ID <100), очевидно, выполняется в .NET . </p>
Кроме того, если я заменю второй фрагмент кода на
var models = MyRepository.GetActiveMyModel();
var filtered = from m in models
where m.Items.Count > 0
select new { m.Name };
Он генерирует исходный SQL для извлечения активных записей, а затем запускает отдельный оператор SQL для каждой записи, чтобы узнать, сколько элементов у него есть, вместо того, чтобы писать что-то, как я ожидал:
SELECT Name
FROM MyModel m
WHERE Active = 1
AND (SELECT COUNT(*) FROM Items WHERE MyModelID = m.ID) > 0
Anthony