Сложный проект ASP.NET: выбор ORM?

Вопрос поднимался не раз, но все же нигде нет исчерпывающего ответа, поэтому извините, пожалуйста.
Итак - КАКУЮ ORM выбрать для сложного многоуровневого проекта на ASP.NET MVC, в котором есть множество видов запросов - и сложные выборки с кучей join-ов, сложные запросы на обновление данных, вставка-удаление тысяч записей и т.п.

Дело в том, что проект мигрирует с php на asp.net и, как ни странно, в PHP + MySQL более десяти лет хватало голых запросов к базе плюс небольшой обертки для маппинга select-ов, несмотря на сложность запросов, в основном за счет существования конструкции "ON DUPLICATE KEY UPDATE".

В T_SQL такого нет. В предыдущей работе с приложениями Windows я пользовался классическим Dataset и этого хватало. Сейчас надо выбирать какую-то ORM, поддерживающую кеширование данных (как Local в EF), быстрый маппинг на голом SQL (как Dapper), bulk upsert (EF.Utilities / SQLBulkCopy).

Какого-то продукта, который сочетает полную функциональность для всех задач, я так и не нашел.
EF универсален, но сильно проигрывает по производительности в простых селектах, где нужен быстрый меппинг, в upsert (которого тупо нет, есть только отдельный insert/update либо AddOrUpdate, генерирующий ДВА запроса на каждый Entity), в сложности построения linq для сложных больших запросов (для сравнения, формирование raw-sql для кучи условий заняло примерно 70 строк с учетом форматирования, а конвертированный в Linqer запрос занял сотню строк и это без половины условий).
Dapper позволяет влегкую выбирать данные, используя сложнейшие raw-запросы, но не умеет работать с upsert.
EF.Utilities/SqlBulkCopy не встраиваются органично в EF, то есть для их использования нужно писать код отдельно, уходя от стандартного функционала EF.

Какие ORM существуют для решения всех вышеперечисленных задач комплексно? Может быть, есть некие гибридные связки (как EF + Dapper, о чем часто встречаются упоминания), кастомные решения в NuGet?
Хочется видеть DbContext, в котором реализована вся функциональность EF плюс туда же внедрен Dapper для работы с raw-запросами с возможностью внедрения полученных сущностей в DbContext DbSet-ы автоматом, с учетом отслеживания, плюс реализована функциональность bulk upsert БЕЗ дополнительных танцев с бубном (вызов SaveChanges и дальше ORM сама решает, какие данные на основе указанных ключей вставить, какие обновить, надо ли возвращать идентификаторы для отслеживания записей и т.п.).

Может быть, стоит уйти от MSSQL и работать в связке с MySQL, учитывая наличие конструкции "ON DUPLICATE KEY UPDATE"?
  • Вопрос задан
  • 3107 просмотров
Решения вопроса 1
@Oblomingo
Советую вам задуматься не только об ORM, но и об архитектуре вашего приложения.
ORM позволяет очень быстро реализовать слой ответственный за трансформацию моделей базы данных в обьекты бизнес модели. Фактически, он реализует кучу таких классических паттернов как Data Mapper, Identity Map, Lazy Load, Repository, Unit of Work и еще кучу всего. Все это вы получаете из коробки + такие приятные вещи для контроля версии базы данных как CodeFirst + migrations. Да, в отдельных случаях вы расплачиваетесь скорость чтения/записи.
Тут вам должна помочь правильная архитектура вашего приложения. Вы можете проектировать в соответсвии с принципами Domain-Driven-Design. В этом случае (в отличие от монолитного решения) приложения разделено на части. Каждая часть может иметь свою инфраструктуру, которая умеет записывать/читать данные из базы данных (repository pattern) и использовать какой то отдельный фреймворк. Части, которым не актуальна быстрая скорость, может легко использовать удобыный EF. Если в какой то части вы видите проблемы с быстродействием (bottleneck), вы можете изменить repository - выкинуть из нее EF и использовать Dapper. При правильной архитектуре, такая замена не затронет другие части системы и ваш рефакторинг пройдет безболезнено.

Кроме того для EF есть расширения, которые реализуют Bulk функции:
https://github.com/loresoft/EntityFramework.Extended
entityframework-extensions.net
https://efbulkinsert.codeplex.com/
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
dmitry_pavlov
@dmitry_pavlov
World-class .NET freelance contractor (remotely)
Я бы сначала сделал миграцию как таковую, а потом бы уже подбирал ORMы под те ли иные нужды. Единственно - желательно архитектурно работу с данными убрать в некий data access layer (чтобы потом можно было, покрыв тестами, править только его, не сильно трогая код выше уровнями). Миграцию в данном случае тогда делать лучше на голом ADO.NET так как он позволяет делать с базой все что вам надо всеми перечисленными способами.

Когда переедете с PHP можно будет заняться уже ORMами. Для CRUD операций нормально подойдет EF. Для bulk update/insert-ов - возможно проще оставить ADO.NET (такие операции я бы еще сделал асинхронными для обработки в бекграунде с последующей нотификацией об окончании - через опрос или через push уведомления - скажем WebRTC). Для выборок со сложными запросами - убрать эти сложные запросы в хранимые процедуры и дергать их либо через EF либо через ADO.NET. На счет маппинга данных на объекты используемые выше уровня data access - использовать AutoMapper. С его помощью можно смапить что-угодно на что угодно, главное не полениться и разобраться с возможностями его конфигурирования.

Единой ORM, которая хорошо охватит все перечисленные виды работы с данными и при этом будет оптимальной для всех, просто не может быть. У всех ORM в основе есть та или иная концепция - как надо работать с данными. Универсальные же системы - это когда все части работают одинаково (причем одинаково плохо обычно :) ).
Ответ написан
Могу предложить взглянуть на Flexberry ORM. Он проектировался как раз для разработки сложных систем с длительным сроком сопровождения и доработок. Для полного цикла создания есть Фреймворк под ASP.NET (но, к сожалению только WebForms) или вариант связки OData + EmberJS.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы