Кажется, я нашел ответ на свою "проблему". Моя проблема на самом деле была не проблемой, а скорее неправильным мышлением.
Когда я прочитал это Мне стало ясно, что я просто хотел найти решение неправильной проблемы. Позвольте мне объяснить, что ....
Я использую шаблон 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 сохраняет выражение из-за отсутствия .compile() и может использоваться в sql.
Меня это почти устраивает. Что меня раздражает, так это необходимость вызывать ".compile()", и я до сих пор не понимаю, как я должен построить или позволить одному выражению использовать другое выражение, которое кажется невозможным, кроме как вызовом .compile() включая его, потому что это снова только ICollection, на который я не могу помещать объекты Expression. Я полагаю, что здесь я могу использовать LINQKit, который затем удаляет вызовы compile().
Надеюсь, я иду в правильном направлении. Если вы обнаружите какую-либо логическую ошибку или придумаете, как это сделать лучше, сообщите мне об этом в комментариях, чтобы я мог обновить ответ. Спасибо всем!
person
letmaik
schedule
05.04.2010