Продолжая взаимодействие с настоящим сайтом, вы выражаете свое согласие с тем, что ваши пользовательские данные (сведения о местоположении; тип и версия ОС; тип и версия Браузера; тип устройства и разрешение его экрана; источник откуда пришел на сайт пользователь; с какого сайта или по какой рекламе; язык ОС и Браузера; какие страницы открывает и на какие кнопки нажимает пользователь) будут обрабатываться ООО «Тадос» в целях сбора статистических данных о посетителях сайта и функционировании сайта в течение 3 месяцев. В случае, если вы не хотите, чтобы ваши данные обрабатывались, покиньте сайт.

Как правило в проектах уровня Enterprise для слоя работы с данными мы используем NHibernate (далее NH) + автомаппинг Fluent NH. До недавних пор нас это вполне устраивало.

NH прекрасно сочетается с DDD, позволяет шикарно манипулировать данными (речь как минимум о каскадах), сокращает затраты на изменение кода при развитии домена. А это неизбежно, пока жив проект. Впрочем, и для чтения данных его хватало.

Безусловно, были моменты, когда при построении отчетов приходилось что-то придумывать, увидев очередное «Not supported». В основном это мелочи из разряда «Хочешь использовать фреймворк / технологию — вот тебе рамки».

Но чем дальше, тем запутаннее становился Linq и тем больше появилось комментариев формата «Сделал так, потому что NH не дает / не поддерживает / неправильно строит SQL».

Шло время и все это набрало критическую массу. Пара примеров:

  1. Отсутствие поддержки Union;
  2. Реализация LEFT OUTER JOIN в Linq представлена GroupJoin-ом. После объединения таблиц часто хочется отфильтровать результаты. Однако NH не умеет маппить в SQL условие после GroupJoin;
  3. Очень странный маппинг в SQL агрегирующих функций после группировки объединенных таблиц.
    Допустим, мы сгруппировали какие-то данные и получили IQueryable<Entity> entities. При вызове entities. AsEnumerable ().Count () И entities. Count () мы можем получить разные результаты. В первом случае получим запрос вида «SELECT X … GROUP BY X», во втором вместо подсчета количества кортежей в таблице с результатами группировки получим «SELECT COUNT (X) … GROUP BY X».
    Нам просто предлагают получить количество кортежей после объединения. И так с любой агрегирующей функцией.

article_nhibernate

Список можно продолжать. Кстати, entities. Count () могло без проблем уйти в продакшен, если бы не правильно подобранные нашим разработчиком Михаилом тесты. Это хороший пример сложно диагностируемой проблемы при использовании NH. Сколько еще подобных возможных ситуаций — вопрос открытый. Вряд ли кто-то может позволить после каждого запроса смотреть SQL в профайлере, чтобы убедиться в правильности генерации. Или наоборот — не вылазить из исходников NH перед написанием каждого Linq.

Самое плохое, что чем дальше, тем более громоздким становится Linq. Да, мы добиваемся того, что сгенерированный SQL выглядит именно так, как мы бы того хотели (читай — как бы мы написали на plain SQL). Но для этого требуется много времени и в десяток раз больше кода, чем просто запрос на plain SQL. И чем дальше, тем больше желание не использовать NH для слоя чтения (только чтения!) данных.

Да, часть из описанных проблем в NH пофиксили. Но мы встретились с новыми. На текущий момент смотрим в сторону Dapper. Разработчики уверяют, что потерь в производительности по сравнению с использованием SqlDataReader практически нет.

Если кто-то пользовался этой «микро-ORM», поделитесь практикой или просто впечатлениями.

P. S. StackOverflow кстати использует Dapper.

— Константин Рожков, тимлид Tados

* Обязательные поля

Нажимая на кнопку «Подписаться на новые статьи по разработке» вы даете согласие на обработку своих персональных данных

О проблемах с NHibernate в одном из проектов
Средняя оценка 5 Проголосовало 4