Pull to refresh

Comments 17

Текстовые запросы при наличии выражений и IQueryable не радуют

Если уж вы ищите легковесные ORM, то не проходите мимо linq2db. LINQ превращает все что вы тут сгенерили в легкую прогулку. LINQ запро на копирование, удаление тоже возможен.

Спасибо, за комментарий. Сейчас как раз рассматриваем возможность перехода на linq2db, но пока уперлись в скорость работы, все таки linq2db работает медленнее чем Dapper и сложные запросы писать в SQL синтаксисе как по мне проще, нагляднее, и предсказуемее + Rider позволяет их сразу из кода выполнить и протестить без запуска приложения.

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

Вот я так и тестирую запросы во время исполнения. Так как разбираю запрос на маленькие и каждую часть спокойно могу проверить на правильность выборки.

Для автоматического маппинга от snale_case к PascalCase можно проставить флаг:

DefaultTypeMap.MatchNamesWithUnderscores = true;

Действительно так можно сделать, но здесь скорее суть в том что часто в БД и в запросах названия различаются, например в БД поле dt а в коде мы хотим иметь возможность назвать его Date + не хочется чтобы при рефакторинге поломались запросы если например в коде мы захотим переименовать Date в LastDate, поэтому я вижу более безопасным прописывать свойства напрямую через nameof()

Вы слишком много думаете о ситуации "если например в коде мы захотим переименовать".

Если у вас в БД колонка называется так, то и в коде называете её так же. Если хотите переименовать - переименовывайте и там, и там. Не заставляйте людей, которые будут читать ваш код гадать, как сопоставить свойства класса с колонками в БД.

В такой ситуации MatchNamesWithUnderscores прекрасно работает и никакие nameof не нужны. (такие запросы не читабельные совсем).

Ну в нашей ситуации тяжело вести актуальность БД со всей кодовой базой, поскольку бывают случаи когда одна таблица используется для нескольких микросервисов на readonly и изменение схемы ведет к необходимости изменения всей кодовой базы в разных репах что довольно-таки трудозатратно.

Так же часто возникает необходимость маппить одни и те же данные на различные бизнес сущности и в них названия могут отличаться по смыслу.

Тут все зависит от подхода работы с БД, у нас классы не являются Entity а представляют некую бизнес-часть и слабо связны с БД, при этом один класс может наполняться данными сразу из многих таблиц, либо данные из одной таблицы могут накачиваться в различные классы в процессе жизни приложения.

Поэтому несоответствие названия поля в БД и свойства в классе для нас абсолютно нормальное явление поскольку структура классов не повторяет БД 1 в 1, в тестовых примерах в статье к сожалению не получилось подробно раскрыть эту тему

Dapper конечно имеет свою нишу применения, но, я вас умоляю, не называйте его "ORM", потому что он таковым не является. ORM это далеко не только "представить результаты SQL-запроса в виде объекта", а еще и куча других паттернов, таких как "identity map", "change tracking", "unit of work" и т.п. Мы однажды связались с Даппером, но когда стали требоваться все более и более сложные сценарии, то, в итоге, с матюками переписали все на EF.

Ну сами создатели Dapper позиционируют и называют его micro-ORM (Object–relational mapping), так что это не я придумал)

А по поводу использования EF для более сложных сценариев не соглашусь, поскольку есть противоположный пример отказа от тяжеловесной EF.
EF тесно имплементирует сущности БД в архитектуру проекта и при увеличивающейся сложности бизнес-процессов внутри вашего проекта дает эффект, что код сервиса начинает сильно завесить от БД и небольшие изменения в бизнес-логике будут всегда вести к изменению схемы БД.

Мы же стараемся придерживаться подхода что БД отвечает только за хранение данных и выбираем структуру, схему и вид БД исходя из данных.

В то время как код приложения написан по DDD и старается моделировать бизнес-процессы такими какие они есть и соответственно классы отражают реальные физические объекты и их свойства, без понимания того как они хранятся в БД.

А Dapper в этой связке как раз и позволяет нам просто наполнить наши классы данными, например у нас есть часть классов которые вообще наполняются из mongo и redis)

P.S. Соглашусь что Dapper подходит не для всех проектов и не является серебрянной пулей, в данной статье просто хотел показать как выглядит код и способ работы с этой библиотекой

я как в 2010 попал , мы шилим стриминговые материализованые базы данных , хитрейшие ОРМы , а тут ORM на конкатенации строк )

Ну, в 2022 это все ещё используют ребята из stackoverflow которые и являются по совместительству разработчиками Dapper, на котором и держится их система)

Ну и никто не запрещает комбинировать EF или linq2db для простых запросов не требующих высокой скорости и Dapper для мест где работа с БД требует скорости и тонкой оптимизации. Как раз на эту тему у ребят на страничке в github есть бенчмарки https://github.com/DapperLib/Dapper

Они его используют потому что он все хорош, или потому что за эти годы собрали огромную кодовую базу, и потому что "тут так заведено" ?

На основе последних бенчмарков EF Core 6.0 c Dapper, когда разница в производительности составляет 5-10%, нету вижу особого смысла выбирать Dapper. Я отдаю предпочтение строго типизированному, покрытому тестами (in-memory) кодом, генерации оптимальных запросов на основе отслеживаемых данных. EF в данном плане явный фаворит.

Скул в тексте - это всегда красиво. А приправленный nameOf, так шедевр базопостроения. Институтом и лекциями пахнет. Нет?

Если верить докам ms, то разрыв между dapper и efcore6, при желании сокращается до 5%. Есть о чем подумать. В dotnet7 обещают какой-то взрыв производительности, может быть разрыв сойдет на нет совершенно.

Sign up to leave a comment.

Articles