дизайн интерфейса с Linq2Nibernate и IQueryable

При использовании Linq2Nibernate лучше заставить репозиторий возвращать IQueryable?

Насколько я понимаю, если вы используете Linq для Nibernate, запрос не будет «срабатывать», пока вы не вызовете .First () или Single () и т. Д. Так не лучше ли было бы возвращать IQueryable из всех ваших интерфейсов, чтобы вы могли создавать \ манипулировать деревом выражений до того, как оно сработает?

Мои репозитории вызываются службами и наследуются от IServicie.

РЕДАКТИРОВАТЬ:

Во-первых, я очень ценю все ответы. Но я хочу кое-что добавить к вопросу. Я за этот дизайн. Я не совсем понимаю оговорки по поводу тестирования. Пока процесс тестируется в каждой точке IE в каждой точке фильтрации, я не вижу большой разницы.

добавление:

Есть ли смысл использовать Linq2Nibernate, если ваш репозиторий не возвращает IQuerrable?


person Ted Smith    schedule 12.03.2009    source источник


Ответы (3)


Лично я думаю, что нет. Проблема с раскрытием составных запросов из вашего репозитория заключается в том, что вы больше не можете полностью тестировать их - их поведение (и успех) теперь во власти вызывающего. Например, они могут сделать .Where(x=>SomeUnmappedMethod(x)) (без перевода). Я добавил дополнительную информацию об этом здесь.

Если у вас есть фиксированные методы, которые возвращают (например) IList<T> или T[], тогда вы можете быть уверены, что если он работает в модульном тесте, он должен работать реально (за исключением любых ошибок конфигурации). Это также означает, что вы можете профилировать DAL изолированно и иметь разумную уверенность в том, какой SQL (и т. Д.) Будет выполняться. Вы не можете профилировать / оптимизировать DAL, который изменяется в зависимости от вызывающего абонента.

(на основе моего использования LINQ-to-SQL; не конкретно LINQ-to-NHibernate)

person Marc Gravell    schedule 12.03.2009
comment
Что касается изоляции, разве вы не столкнетесь с тем, что вызывающий абонент обращается к отношениям, которые вы не загрузили? - person eglasius; 12.03.2009
comment
Я понимаю, о чем вы говорите, ДЕЙСТВИТЕЛЬНО ценю ваш вклад, но разве это не означает, что Linq2Nibernate на самом деле используется в полной мере? Я не вижу никакой пользы в его использовании, если вы не можете применить шаблон типа каналов и фильтра Выборка из базы данных PRE - person Ted Smith; 12.03.2009
comment
@Ted вы используете шаблон спецификации, который может работать очень похожим образом ... в основном вы передаете эти фильтры методу (в отличие от их применения после вызова метода) - person eglasius; 12.03.2009
comment
@Marc, возможно, вы захотите уточнить, что это интеграционные тесты, см. Правку chad и мой комментарий к ней. - person eglasius; 13.03.2009
comment
Вы можете использовать все содержимое LINQ внутри репозитория ... или использовать IQueryable - на ваше усмотрение ... - person Marc Gravell; 13.03.2009
comment
@Freddy - Я бы сказал, что проверка того, что DAL выполняет свою работу, является модульным тестом; Я хочу избежать необходимости проводить интеграционный тест между потребителем и репозиторием - и это то, что необходимо, если вы открываете IQueryable - person Marc Gravell; 13.03.2009
comment
@Marc Я понимаю, что вы имеете в виду, и я согласен, вызов тестов, которые обращаются к модульным тестам внешних систем, обычно вводит людей в заблуждение :( - проверьте, что я разместил здесь: stackoverflow.com/questions/589603/ - person eglasius; 13.03.2009

Это зависит от того, что использует ваш «Репозиторий» (кавычки из-за двусмысленности). Я бы сказал, что если что-то вроде вашего последнего слоя (UI) использует ваши классы репозитория, чтобы НЕ возвращать IQueryable. Однако, если у вас есть еще один уровень между уровнем пользовательского интерфейса и уровнем доступа к данным, я бы сказал, что да, верните IQueryable и пусть ваш средний уровень обрабатывает выполнение запроса.

ИЗМЕНИТЬ

Что касается тестирования вашего уровня доступа к данным (DAL) / репозитория, я бы сказал, что по большей части, если у вас нет реальной логики (если операторы и т. Д.), Тестирования не должно быть практически никакого. На этом этапе вы тестируете фреймворк. Я предлагаю разместить еще один уровень между вашим уровнем доступа (UI) и DAL, например BLL или что-то, что обрабатывает выполнение запросов IQueryable. Таким образом, ваш репозиторий может возвращать запросы, а ваш BLL может обрабатывать их выполнение и, возможно, выполнять некоторую логику, которая затем может быть протестирована.

person Chad Moran    schedule 12.03.2009
comment
в данном случае это не тестирование фреймворка, а интеграционное тестирование - проверка того, что он работает с текущей версией базы данных, то есть у кого-то не было шанса сломать его ... Я был обеспокоен тем, что Марк назвал это модульным тестированием, что это неправильный взгляд на это - person eglasius; 13.03.2009

Я не использую IQueryable, но объясню, почему я поступаю иначе:

  • Проще смоделировать репозиторий, протестировать другой код, который его использует.
  • Интеграционные тесты - большая часть того, что вызывает запуск запроса, находится в репозитории, поэтому я могу провести несколько действительно целенаправленных интеграционных тестов против него.
  • Относительно первого, легче проверить код, выполняя соответствующие вызовы репозитория. Это связано с тем, что вызывающий код будет передавать информацию о фильтрах вызову метода репозитория, а не применять их к результатам.
person eglasius    schedule 12.03.2009