Это хороший вопрос, и ИМХО они могут масштабироваться так же, как и любой пользовательский DAL. Я использовал только nHibernate, поэтому я сосредоточусь только на нем и его возможностях, которые могут помочь масштабировать систему.
- Ленивая загрузка - поскольку он поддерживает отложенную загрузку, вы можете избежать загрузки любых ненужных предметов. Конечно, вам нужно остерегаться проблемы Select n + 1, однако в системе есть что-то, чтобы это предотвратить.
- Стремительное извлечение. Существуют различные способы оперативного извлечения объектов, которые могут вам понадобиться, что позволяет избежать дополнительных поездок в SQL.
- Кэш второго уровня - nHibernate поддерживает кэш второго уровня, который можно использовать для повышения масштабируемости за счет сокращения обращений к БД. Существуют различные поставщики поддержки, которые дают вам некоторую гибкость.
- Напишите свой собственный SQL - В nHibernate вы можете вызывать хранимые процедуры или предоставлять встроенный SQL-запрос, который будет возвращать ваши сущности. Это позволит вам использовать свой собственный SQL, когда сгенерированный sql его не обрезает. Например, стремясь загрузить самосоединяющееся дерево с помощью рекурсивного запроса.
Теперь, с учетом вышесказанного, я думаю, что проще изначально настроить пользовательский слой DAL, потому что вы хорошо знакомы с его конструкцией и можете точно его настроить; тем не менее, хороший ORM обеспечит множество хуков, которые позволят вам немного оптимизировать. Вам просто нужно потратить некоторое время на изучение этого.
Мне также кажется, что если у вас есть область кода, критичная к производительности, и вы не можете заставить свой ORM работать в соответствии с вашими требованиями, то для этой крошечной области вашего приложения вы можете создать собственный слой DAL. Если вы используете достойный шаблон проектирования, такой как репозиторий, созданный на фабрике, то все, что вам нужно сделать, это поменять реализацию вашего репозитория