G>>>Да, разница огромная. CheckAllQueries не работает с динмическим SQL. AP>>Ты читать не умеешь? Там всё начинается с динамического SQL. G>И заканчивается тонной тестов, которые не явлются проверкой при компиляции. G>Как раз читать я умею, даже умею читать то, что явно не написано.
Тесты генерируются автоматически, человек в этом не участвует, в чем отличие от компиляции?
Здравствуйте, Alexander Polyakov, Вы писали:
G>>>>Да, разница огромная. CheckAllQueries не работает с динмическим SQL. AP>>>Ты читать не умеешь? Там всё начинается с динамического SQL. G>>И заканчивается тонной тестов, которые не явлются проверкой при компиляции. G>>Как раз читать я умею, даже умею читать то, что явно не написано. AP>Тесты генерируются автоматически, человек в этом не участвует, в чем отличие от компиляции?
Code talks, bullshit walks. Выложи проект.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Code talks, bullshit walks. Выложи проект. AP>Для публичного релиза надо много почистить, но вот выложил. Смотреть Demo\Program.cs.
А где же проверка при компиляции?
Убрал скобку, получил TEI с абсолютно невнятным сообщением что не так.
Работает дико медленно. На этот запрос уходит 2 секунды на тесты, в реальном приложении с сотнями запросов можно долго ждать.
Нереальное количество кода, не знаю что из этого пишется руками, но выглядит страшно.
Как это будет работать при декомпозиции? Когда разные части запроса в разных сборках.
Как я понял параметры пишутся прямо в тело зарпоса, это вызовет plan cache pollution на sql server. Для продакшена нерабочее решение по факту.
G>Убрал скобку, получил TEI с абсолютно невнятным сообщением что не так.
Пости сюда полную распечатку исключения. Объясню, что это сообщение означает.
G>Работает дико медленно. На этот запрос уходит 2 секунды на тесты, в реальном приложении с сотнями запросов можно долго ждать.
Это известное поведение, связано с Roslyn Preview. В Known issues для Roslyn написано:
o After starting Visual Studio, the first build may be slower than expected due to the compilers not being NGen’d in the Preview.
У меня на машине Roslyn установлен через сетап, поэтому он прошел NGen. Можно самому прогнать NGen из консоли (с этим я тоже экспериментировал). У меня на машине CheckAllQueries выполняется 229ms, причем существенную часть занимает открытие первого connection-а. На проекте с сотнями запросов CheckAllQueries укладывается в полторы секунды.
G>Нереальное количество кода, не знаю что из этого пишется руками, но выглядит страшно.
Я думал, ты просил код, чтобы читать его. Руками ничего не пишется. То, что ты называешь "нереальное количество кода" уйдет в библиотеку, я ж предупредил, коду требуется серьезная чистка. Ты смотри, где заточка на конкретный запрос? Такой заточки нет.
G>Как это будет работать при декомпозиции? Когда разные части запроса в разных сборках.
Выложил пример.
G>Как я понял параметры пишутся прямо в тело зарпоса, это вызовет plan cache pollution на sql server. Для продакшена нерабочее решение по факту.
Твой механизм понимания дал сбой, чтобы убедиться в этом, достаточно посмотреть в SQL Profiler и увидеть там параметризованные запросы.
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Убрал скобку, получил TEI с абсолютно невнятным сообщением что не так. AP>Пости сюда полную распечатку исключения. Объясню, что это сообщение означает.
Даже не хочу связываться, лучше я Linq буду пользоваться.
G>>Как я понял параметры пишутся прямо в тело зарпоса, это вызовет plan cache pollution на sql server. Для продакшена нерабочее решение по факту. AP>Твой механизм понимания дал сбой, чтобы убедиться в этом, достаточно посмотреть в SQL Profiler и увидеть там параметризованные запросы.
Вижу, не туда смотрел.
G>Под отладчиком дико тормозит...
У меня такое поведение не воспроизводится. Под отладчиком тормозов не наблюдается. Возможно, это также связано с тем, что сборки Roslyn не прошли NGen. Надо на чистой виртуалке будет погонять.
Или может ты опять не туда смотришь...
Здравствуйте, Alexander Polyakov, Вы писали:
G>>Под отладчиком дико тормозит... AP>У меня такое поведение не воспроизводится. Под отладчиком тормозов не наблюдается. Возможно, это также связано с тем, что сборки Roslyn не прошли NGen. Надо на чистой виртуалке будет погонять. AP>Или может ты опять не туда смотришь...
Часы точно идут. Почти 10 сек на прогон тестов одного сложного запроса.
Здравствуйте, btn1, Вы писали:
B>Потому что те, кому я отвечаю, съехали в какие-то дебри и толкают мысли, которые интересны только им. Может у меня что-то с русским языком, но я с трудом нахожу общность между моим B>
Это потому, что вы пренебрегаете существенными деталями.
B>Во-первых, речь вообще не про апгрэйд, а про принципиальные возможности хранимок и кода на ЯВУ внутри модели.
Вы задаёте общий вопрос "зачем могут быть нужны хранимки", но почему-то ожидаете ответа только в одной узкой области. Но выбор способа реализации не исчерпывается рассмотрением характеристик функциональности и производительности.
B>Я отвечу на этот второстепенный вопрос, но продолжать "тему обновлений" не вижу смысла — вы ушли от главного и мусолите детали. B>1. Даже если мы возьмём систему, где широко используют хранимки, в ней всё равно не избежать какой-то логики на стороне сервера приложений (рассматриваются только трёхзвенные системы как наиболее передовая архитектура).
Вы опять не читаете то, что вам пишут. Трёхзвенными системами мир не исчерпывается. Но если мы переходим к трёхзвенке, аргумент про 1500 клиентов исчезает, т.к. у базы остаётся только один клиент.
Тогда причин использовать хранимки остаётся мало. Например, для MS SQL Server объективных причин не остаётся совсем.
B>2. Если у вас 30 филиалов, очевидно, что этим занимается далеко не один человек. Распределить задачу обновления — административная хрень.
Не стоит преуменьшать важность административных хреней. Если вы разработчик, то администраторы — ваши клиенты. В нашем насквозь прогнившем коммерческом мире класть болт на потребности клиентов — не лучшая идея.
B>3. Если для вас "остановить сервер, обновить, запустить" — проблема, то наверное есть смысл улучшить свою квалификацию?
Для меня — нет, не проблема. А в какой-нибудь телекоммуникационной компании минута простоя удачно выбранного сервера обходится примерно в $2M. С этой точки зрения есть принципиальная разница в остановке сервера на 30 секунд и на 30 минут.
B>Вопрос "обновления" — вопрос ни о чём, с тем же успехом можно обсудить подсветку T-SQL в студии — это далеко не самое интересное в вопросе "хранимки vs код".
Ну, я догадываюсь, что конкретно вас может интересовать. Хотя намеренно сужать область своих интересов — странно.
Ок, поясню в рамках выбранной вами модели (трёхзвенное приложение): для "взрослых" СУБД различий практически нет. Потому что возможности интерактивного и процедурного диалектов совпадают. А вот, скажем, в interbase до сих пор есть три разных диалекта. В интерактивном SQL (т.е. в том, который уезжает с клиента) нету процедурных расширений — т.е. никаких if или циклов. Все ветвления придётся делать на стороне клиента, а это — раундтрипы. В особо удачных случаях время исполнения запроса может только из-за этого вырасти в разы. А это, в свою очередь, означает удлинение удержания блокировок, и оказывает каскадный эффект на производительность. Понятно, не в лучшую сторону.
Вот в таких случаях хранимые процедуры по-прежнему объективно выгодны.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Что то мне подсказывает, что 1500 клиентов в 30 офисах, которые напрямую лезут в БД без какого либо middleware — отличный способ прострелить себе яйца ногу, вне зависимости от количества хранимок.
Ну, это и есть причина, по которой от client-server девяностых ведущие собаководы перешли к трёхзвенке
Тем не менее, как мы знаем, старые приложения не умирают. Просто новые пишутся с такой скоростью, что их процент растёт
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
B>>1. Даже если мы возьмём систему, где широко используют хранимки, в ней всё равно не избежать какой-то логики на стороне сервера приложений (рассматриваются только трёхзвенные системы как наиболее передовая архитектура). А значит "обновления хранимок" — лишь часть того, что нужно обновлять на сервере, т.е. мы по-любому не избегаем процедуры обновления сервера.
В нормальной современной трёхзвенке логика в триггерах и хранимках — адское зло.
Потому, что бизнес-логика распиливается на две части, без каких-либо очевидных правил выбора.
При написании кода разработчик мечется между тем, чтобы написать новую хранимку, поправить старую, или просто зафигачить код на шарпе. Править базу — страшно, потому что в отличие от кода на шарпе, никто тебе не покажет все места использования. В итоге рождаются уродцы типа "давайте вызовем хранимку, а потом выкинем все результаты, кроме первого", убивающие производительность.
Рефакторинг такого слоёного пирожка — тоже кошмар.
Ну и вообще — все случаи боевого применения такой ерунды, которые видел лично я, сводятся к хранимкам для CRUD. За такое вообще надо сразу приговаривать по статье 332.3 УК, за неимением более подходяшей статьи. А если такое встречется в коммерческом проекте — то по законам военного времени.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Кстати, почему в Java 8 сделали LINQ to Object и не сделали LINQ to Database? Вот мнение
Оно неправильное. Весь ответ в том, что Java разрабатывают кретины. Сначала 5 лет делали generic'и, и умудрились их сделать самым кривым из возможных способов. Он оказался:
1) Обратно несовместим — код с generic'ами для JRE 1.5 не мог работать на JRE 1.4
2) С type erasure, который изначально делался в попытках сохранить совместимость с пунктом 1.
Потом Sun начал делать лямбы, которые им пришлось осиливать аж 10 лет. Это уже была просто полнейшая некомпетентность сразу по всем направлениям.
Здравствуйте, Cyberax, Вы писали:
C>Оно неправильное. Весь ответ в том, что Java разрабатывают кретины. Сначала 5 лет делали generic'и, и умудрились их сделать самым кривым из возможных способов. Он оказался: C>1) Обратно несовместим — код с generic'ами для JRE 1.5 не мог работать на JRE 1.4 C>2) С type erasure, который изначально делался в попытках сохранить совместимость с пунктом 1.
А почему код с generic'ами для JRE 1.5 не мог работать на JRE 1.4, если типы херятся?
Здравствуйте, Sinclair, Вы писали:
S>Ну и вообще — все случаи боевого применения такой ерунды, которые видел лично я, сводятся к хранимкам для CRUD. За такое вообще надо сразу приговаривать по статье 332.3 УК, за неимением более подходяшей статьи.
По моему статья 228 отлично подойдет для таких случаев.
Здравствуйте, Jack128, Вы писали:
C>>1) Обратно несовместим — код с generic'ами для JRE 1.5 не мог работать на JRE 1.4 C>>2) С type erasure, который изначально делался в попытках сохранить совместимость с пунктом 1. J>А почему код с generic'ами для JRE 1.5 не мог работать на JRE 1.4, если типы херятся?
Два ответа:
1) Версия байт-кода у JDK 1.5 другая, так что JDK 1.4 их не понимает.
2) Пришлось так сделать из-за того, что массивы позволяют обходить типизацию.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Sinclair, Вы писали:
S>>Ну и вообще — все случаи боевого применения такой ерунды, которые видел лично я, сводятся к хранимкам для CRUD. За такое вообще надо сразу приговаривать по статье 332.3 УК, за неимением более подходяшей статьи. G>По моему статья 228 отлично подойдет для таких случаев.
Ну, формально-то мы говорим о 273/2, но по смыслу нужна статья из 33 главы, но в нынешних редакциях её нет.
А если по главе 25, то надо инкриминировать 230, 237 и 238.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Cyberax, Вы писали:
C>Оно неправильное. Весь ответ в том, что Java разрабатывают кретины. Сначала 5 лет делали generic'и, и умудрились их сделать самым кривым из возможных способов. Он оказался: C>1) Обратно несовместим — код с generic'ами для JRE 1.5 не мог работать на JRE 1.4 C>2) С type erasure, который изначально делался в попытках сохранить совместимость с пунктом 1.
Куда смешнее другое — в дотнете дженерики сделали с существенными ограничениями и ввели констрейны, так как там дженерик компилируется как дженерик, а конкретные аргументы в него подставляются в рантайме. Это дает свои плюсы, но накладывает ряд ограничений. В джаве же дженерики почти исключительно компиляторный сахар, так что всякую фигню типа использования параметра типа в качестве базового класса реализовать было несложно. Вобщем, карго-культ какой то.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>А можно вот так написать. Я устранил проблемы связанные с динамическим SQL,
Динамического SQL по ссылке не найдено. Ты не путаешь термин "динамический" с "plain"?
AP>а LINQ всего лишь предлагает новую модель костылей.
Как раз костыль находится по твоей ссылке. Похожий способ, только гораздо круче использовался ещё в примерах к самым первым версиям Nemerle. Но в результате не прижился и так и остался на уровне примера. Причин тому много, но все они так или иначе завязаны на отсутствие типизации. Автоматическая проверка корректности SQL — это хорошо, но это лишь решение одной проблемы, которая в случае LINQ даже не рассматривается.
AP>Всё же предлагаю вести диалог в более предметном ключе. Предлагаю сравнивать LINQ и автоматически проверяемый динамический SQL. Разве есть принципиальная разница: не скомпилируется или не пройдет CheckAllQueries?
Конечно, есть. "Не скомпилируется" выдаёт тебе сразу место проблемы и рассказывает что не так. Check говорит, что не шмагла где-то там, иди, мужик, разбирайся.
AP>Что касается рефакторинга одной кнопкой, то Москва не сразу строилась, прикрутить к моему подходу рефакторинг одной кнопкой тоже можно. Но, честно говоря, в наших проектах время, затраченное на переименование колонки или таблицы пока не настолько велико, чтобы получить видимый выигрыш от продолжения автоматизации рефакторинга.
Во-первых, я очень сильно сомневаюсь, что прикрутить рефакторинг к твоему коду можно. Во-вторых, давай не забывать про навигацию. Переименовывать поле может нужно и не так часто, но искать его использование, получать по нему информацию требуется постоянно.
AP>Вопрос лишь в поддержке со стороны инструментов: ReSharper-а? Или есть принципиальные вопросы?
Думаю, будут проблемы. Для решарпера твой SQL — это всего лишь строковый литерал. Попробуй заставить его думать по-другому.
AP>Отдельный вопрос про LINQ. Вопрос про ассоциации. Откуда они беруться? В реляционных СУБД никаких ассоциаций нет. Там нет такого понятия. Есть только ограничения для поддержания данных в согласованном состоянии. И только эту роль в реляционных СУБД играют внешние ключи. В запросах внешние ключи не используются (кстати, в dbforge отличный автокомплит по FK). Интересно задаться вопросом, почему за многолетнюю историю SQL не один из вендоров не ввел ассоциации, как термин, как элемент метаданных и как элемент синтаксиса SQL?
Надеюсь, претензии к ассоциациям у тебя возникли лишь из желания поспорить. ER диаграмы используются для проектирования СУБД уже десятки лет. Тот факт, что SQL не поддерживает чего-то подобного ассоциациям проблема не ассоциаций, а SQL. Тем не менее любой нормальный дизайн БД без связей между таблицами не обходится, просто потому, что такой дизайн бесполезен. Ассоциация — это всего лишь навсего материализация связи между таблицами, крайне полезная штука, позволяющая экономить тонны кода. При проектировании связи между таблицами определяются всегда, иметь такое ещё и в коде очень круто. И, кстати, некоторые вендоры таки используют ассоциации в своих диалектах SQL.
AP>Может оно и не очень востребовано? Может автокомплита по FK достаточно?
SQL один из самых древних из используемых сегодня языков. Это правда. Но так же он и один из самых консервативных. То же самое относится и к средствам разработки на SQL. Они толком не развиваются и не изменяются годами. Даже наиболее продвинутый тул — Management Studio пребывает почти в одном и том же виде уже десяток лет. За это время в C# появились дженерики, поддержка функционального программирования, LINQ и всерьёз заговорили о реальном метапрограммировании. Т.е. C# пережил в своём развитии несколько поколений, а SQL ни одного. Почему так? Виноват ли в этом C# и LINQ?
AP>LINQ запросы по ассоциациям поддерживает. Поддерживает он ассоциации, потому что рожден в C#/VB, где отдельного понятия "ассоциации" тоже нет, есть свойства. Таким образом, надо ссылочные свойства сишарпа куда-нибудь промэпить в реляционную модель. Вопрос куда? И сколько телодвижений требуется от программиста?
Количество требуемых телодвижений равняется нулю. Ассоциации генерируются автоматически по метаданным из БД.
AP>Как видим, вопрос про ассоциаци связан с тем, что мы исповедуем code first или database first? Code first по сути своей гибридный подход: часть базы определяется в C# коде, часть обычными командами DDL. А такая гибридизация, т.е. двойственность, сама может породить проблемы. Database first выглядит более логичным подходом. Тогда C# классы полностью автоматически генерируются по базе. Но как генерируются ассоциации? По FK? А вдруг мне придется снять ограничения целостности, и что мне переписывать все запросы?
Иногда приходится делать и такое. В этом случае ассоциацию можно дописать русками.
AP>Т.е. одни делают general-purpose язык, другие делают СУБД, а проблемы совместного использования оставляют прикладным разработчикам.
Вообще-то Хейльсберг говорит немного о другом. Ну да фиг с ним.
AP>SqlCommand/SqlReader никакого мэпинга не требуют, работают с СУБД на ее родном языке. SqlCommand/SqlReader не поддерживают статическую проверку запросов? У меня такая проверка добавлена.
Я же говорю. Проверка SQL — это здорово, ты решил одну единственную проблему, которой в случае использования LINQ не существует вообще.
LINQ, конечно, можно и нужно критиковать, это вовсе не идеальный иструмент. Идеальным может стать специализированный встроенный DSL, который транслируется компилятором не в примитивы исполняемого кода, а в термины, близкие к SQL, готовые или почти готовые к исполнению. Тогда можно будет получить очень эффективный и совместимый с SQL инструмент. Но для этого нужно дождаться, когда у разработчиков компиляторов соответсвующим образом повернуться мозги и они дадут нам в руки возможность, позволяющую подружить друг с другом разные языки. Пока же это только мечты. Тем не менее, LINQ — это самый прямой путь к идеалу на сегодняшний день. Ты пытаешься подобраться к этому идеалу с другой стороны, со стороны SQL, а не со стороны компилятора. Сомневаюсь, что у такого подхода есть хоть какие-то перспективы.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Это не делает чести ни банкам, ни биржам. Местами они так, конечно, работают, но видно невооруженным взглядом, что очень плохо работают, медленно и неэффективно. По мере сил мы эту ситуацию меняем и надо признать не без успеха.
Вообще-то в последние лет 5 идет полный отказ вообще от каких-либо технологий "управляемых VM", бо они работают плохо и дают крайне низкую фактическую статистику надежности.
V>>"Полубожественный" доставило. Но это следовало понимать не как божественный, а как "бинго!" для оппонента, от которого за версту несет "поколением next". У меня возникла догадка, она подтвердилась. Всего-то и делов. Другой мир, прям. Других слов нет.
IT>Ты считаешь, что лучше, когда от тебя за версту несёт нафталином и гниловатым запахом разлагающихся технологий? Прямо некрофилизм какой-то. Фу. Ужас.
Я считаю, что если человек не решал сложные задачи, то как бы смешно смотреть, как он учит жизни других. Всё, что может этот человек я могу делать не подключая мозг и даже будучи сильно пьян. Я пытался с ним как-то обсуждать работу дотнетной VM, он даже толком не понимает, как она работает. ))
Да и тебя несет малость. Сейчас не 2005-й год, чтобы так задорно петь дифирамбы дотнету — это нелепо смотрится в 2014-м. Поезд уже ушел. Технология в течении 10 лет показывала себя как ненадежная и неэффективная. Это по-факту попыток использования на крупнейших мировых биржах и банках. Сама платформа еще сырая и ты, как программист, тут бессилен, бо это вне твоей компетенции — ты лишь пользователь платформы. Определённую нишу она заняла — это там, где надо неторопливо выдавать что-то в веб на странички или как веб-сервисы или через родственные веб-ориентированные АПИ. Это ВСЁ! Т.е. из промышленного применения технологии — действительно всё! Там же, где требуется быстро и надежно — прямо на сегодня оттуда сие недоразумение вымыто, как и джава. Увы, сие медицинский факт. И до устаревания этого факта должно пройти примерно десяток лет, не меньше... чтобы критическая масса поколения next превысила опыт потери просто тонн денег и была выполнена еще одна попытка в этом направлении.
И не надо тут пальцы вейром насчет "по мере сил мы эту ситуацию меняем и надо признать не без успеха". Это всё введение в заблуждение непосвящённых читателей. Я прекрасно в курсе ЧТО ИМЕННО могли доверить пилить на дотнете, если речь о биржах и банках.