Если честно, то статья на сегодняшний день малоактуальна. За 20 лет много чего изменилось: появились быстрые мапперы, кодогенераторы, linq в том же c# давно обыденность. "Тяжелые" ORM сейчас, если и имеет смысл использовать, то только для небольших CRUD приложений.
1... Мы полагаемся на поведение драйвера Microsoft.Data.SqlClient
Такое поведение драйвера точно документировано? Вот например в исходниках есть класс ParameterPeekAheadValue с полем FirstRecord типа SqlDataRecord, то есть сохраняется ссылка на первый элемент, данные в котором у вас будут перезаписываться. Возможно, это никак не повлияет на результат, а возможно станет причиной плавающих багов. Ну и смотреть, что поменялось в SqlClient, при каждом обновлении, так себе удовольствие :)
Ну здесь каждый решает для себя сам. Все-таки dapper не ограничивает использование tvp, и если использовать мапперы, то работать будет вполне удобно.
3... Про SqlDataRecord (Важно)
Если код, работающий с итератором, будет работать более чем с одной записью, например через буфер, то будут проблемы без всяких гонок. Если же есть гарантия, что в конкретный момент только одна запись обрабатывается, то да, работать будет. Только как получить такую гарантию?
4... Про linq2db
Когда идет работа с процедурами, то Expression Trees не используются, там чистый маппинг.
Еще не нашел реализаций для IAsyncEnumerable, для хайлоада это важно :)
Интересное решение, но сильно специализированное. Кажется, что для подобной задачи отдельный orm не нужен, достаточно генерировать mapper для табличного параметра.
По поводу конструктивной критики :)
Заголовок полный кликбейт :) Не новый orm обогнал dapper, а tvp обогнал insert...into :) Хотя в тексте и упоминается об этом.
В MapToSqlDataRecord шарится SqlDataRecord. Даже если такой финт сейчас работает, нет гарантий, что не поломается в будущем.
Нет ни одного упоминания о linq2db, там тоже есть поддержка tvp.
На баше удобно только внешние команды через пайпы склеивать. Если логика сложнее пары условий уже проще на другой язык перейти. И если у вас dotnet основная платформа, то C# для скриптов вполне нормальный выбор.
"Используем bind переменные с 2001 года" (tm) :) Поэтому очень странно видеть, что вы хотите еще и автоматическое экранирование идентификаторов. Если такое реализовать на t-строках, то это уже будет не sql для вашей БД, а отдельный dsl.
Хотя бы по той причине, что в запросе вокруг переменной стоят кавычки.
В статье пример для f-строк. Для t-строк кавычки должны быть убраны. Если это не так, то тоже хотелось бы увидеть комментарий автора :)
Изменение sort_column это уже изменение запроса, а не его параметризация. Не знаю ни одной библиотеки доступа к БД с "сырым" sql, которая работала бы на уровне DML. Для такой задачи нужен ORM или SqlBuilder.
Своих миграций у linq2db нет, насколько мне известно. Но никто не мешает использовать другие средства. Я использую ef core, как основной орм, linq2db как вспомогательный, в основном как раз для bulk copy. При этом linq2db строит свои модели на основе DbContext, у него это штатная функциональность.
У меня примерно такой же опыт: раньше писал в txt, когда стал использовать vs code, перешел на md. На Obsidian смотрел, но понял, что он мне не нужен.
Но вроде все ответы по делу, хотя и воды многовато.
Если честно, то статья на сегодняшний день малоактуальна. За 20 лет много чего изменилось: появились быстрые мапперы, кодогенераторы, linq в том же c# давно обыденность. "Тяжелые" ORM сейчас, если и имеет смысл использовать, то только для небольших CRUD приложений.
Нашел в документации рекомендацию использовать один SqlDataRecord. Так что получается, что некоторая гарантия все-таки есть :)
Такое поведение драйвера точно документировано? Вот например в исходниках есть класс ParameterPeekAheadValue с полем
FirstRecordтипаSqlDataRecord, то есть сохраняется ссылка на первый элемент, данные в котором у вас будут перезаписываться. Возможно, это никак не повлияет на результат, а возможно станет причиной плавающих багов. Ну и смотреть, что поменялось в SqlClient, при каждом обновлении, так себе удовольствие :)У dapper есть генераторы для aot.
Ну здесь каждый решает для себя сам. Все-таки dapper не ограничивает использование tvp, и если использовать мапперы, то работать будет вполне удобно.
Если код, работающий с итератором, будет работать более чем с одной записью, например через буфер, то будут проблемы без всяких гонок. Если же есть гарантия, что в конкретный момент только одна запись обрабатывается, то да, работать будет. Только как получить такую гарантию?
Когда идет работа с процедурами, то Expression Trees не используются, там чистый маппинг.
Еще не нашел реализаций для IAsyncEnumerable, для хайлоада это важно :)
Интересное решение, но сильно специализированное. Кажется, что для подобной задачи отдельный orm не нужен, достаточно генерировать mapper для табличного параметра.
По поводу конструктивной критики :)
Заголовок полный кликбейт :) Не новый orm обогнал dapper, а tvp обогнал insert...into :) Хотя в тексте и упоминается об этом.
В MapToSqlDataRecord шарится SqlDataRecord. Даже если такой финт сейчас работает, нет гарантий, что не поломается в будущем.
Нет ни одного упоминания о linq2db, там тоже есть поддержка tvp.
На баше удобно только внешние команды через пайпы склеивать. Если логика сложнее пары условий уже проще на другой язык перейти. И если у вас dotnet основная платформа, то C# для скриптов вполне нормальный выбор.
Плохой пример:
CalculationResultслишком общее название, чтобы понять, что с ним можно сделать. Ничем не лучшеvar:)У него оказывается и поддержка идентификаторов есть) Но как я понимаю, это нестандартная вещь для Python Database API.
"Используем bind переменные с 2001 года" (tm) :) Поэтому очень странно видеть, что вы хотите еще и автоматическое экранирование идентификаторов. Если такое реализовать на t-строках, то это уже будет не sql для вашей БД, а отдельный dsl.
В статье пример для f-строк. Для t-строк кавычки должны быть убраны. Если это не так, то тоже хотелось бы увидеть комментарий автора :)
Это кто как прочитал :) В контексте запроса sql и драйвера БД экранирование это всегда про параметры (bind переменные, плейсхолдеры).
Изменение
sort_columnэто уже изменение запроса, а не его параметризация. Не знаю ни одной библиотеки доступа к БД с "сырым" sql, которая работала бы на уровне DML. Для такой задачи нужен ORM или SqlBuilder.Уже давно можно говорить, что rhel от ibm :)
Не думаю, что процедуры помогли бы вашему проекту. Вы бы сейчас точно также жаловались на трехэтажные запросы и спагетти код в бд.
Своих миграций у linq2db нет, насколько мне известно. Но никто не мешает использовать другие средства. Я использую ef core, как основной орм, linq2db как вспомогательный, в основном как раз для bulk copy. При этом linq2db строит свои модели на основе DbContext, у него это штатная функциональность.
Автор статьи, автор комментария или автор документации? Про других не знаю, а если по поводу пары команд, то достаточно:
Если у дистрибутива есть docker образ, то все танцы сводятся к паре команд.
Вопрос был:
Ответа в тексте LLM нет, только нагромождение общих тезисов.
Это и есть Ado.Net. Но нет спасибо, я лучше через linq2db :)