Я думаю, что нашел ответ на свою "проблему". Моя проблема была не проблемой, а скорее неправильным мышлением.
Когда я прочитал этот , мне стало ясно, что я просто хотел найти решение для неправильной проблемы. Позвольте мне объяснить это ....
Я использую шаблон POCO с EF4 и ленивая загрузка все еще активирована. Благодаря этому я мог магически обходить объекты, не отправляя дополнительные запросы, по крайней мере, они не были видны в моем коде. Но, конечно, для каждого доступа к взаимосвязи отправлялись запросы, и я также наблюдал их с EF Profiler. И, конечно, я также хотел, чтобы они были оптимальными, то есть «использовать условие where в этом sql» вместо «извлекать все строки и выполнять фильтрацию впоследствии». Этот способ мышления также называется преждевременной оптимизацией.
Меня, наконец, поразило, когда я начал думать: "Как бы это было, если бы я не использовал ленивую загрузку?" Проще говоря, все данные, которые мне нужны, выбираются в первую очередь, а затем вы работаете с этими данными и ни с чем, т. Е. Без скрытых запросов. При таком подходе имеет смысл использовать ICollection вместо IQueryable для отношений вашего доменного объекта. И, конечно, я не могу использовать Expression> для вызова .Where () для ICollection, а скорее для внутреннего Func <..>.
Чтобы ответить на мой собственный вопрос, Expression <> должен использоваться только при наличии доступа к хранилищу или о том, что он не является объектом POCO. Если они должны использоваться снаружи, то есть на ICollection, они должны быть скомпилированы с такими объектами Func:
IEnumerable<Comment> comments =
(from c in article.Comments
select c).Where(CommentExpressions.IsApproved.Compile());
И если действительно требуется высокая производительность, то необходимо попросить репозиторий извлечь все комментарии, относящиеся к этой статье, путем сопоставления по идентификатору и места выполнения CommentExpressions.IsApproved. Примерно так:
IEnumerable<Comment> comments =
(from c in dataContainer.ArticleComments
where c.ArticleId == article.Id
select c).Where(CommentExpressions.IsApproved);
Теперь последнее условие where сохраняет Expression из-за отсутствия .compile () и может быть использовано в sql.
Я почти доволен этим. Что меня раздражает, так это необходимость вызывать «.compile ()», и я до сих пор не понимаю, как я должен конструировать или позволить одному выражению использовать другое выражение, которое кажется невозможным, кроме как путем вызова .compile () в то же время включив его, потому что это опять-таки только ICollection, на который я не могу поместить объекты Expression. Я предполагаю, что здесь я могу использовать LINQKit, который затем удаляет вызовы compile ().
Надеюсь, я иду в правильном направлении. Если вы обнаружите какую-либо логическую ошибку или можете придумать лучшие способы сделать это, пожалуйста, сообщите мне в комментариях, чтобы я мог обновить ответ. Спасибо всем!