SQL-запросы не в одном месте, а собираются динамически, проходя через несколько системных слоев. Это хорошая практика? - PullRequest
0 голосов
/ 16 марта 2009

Лично я считаю, что жизнь разработчика, который недавно присоединился к проекту, очень печальная. Без почти полного понимания механизмов фреймворка разработка и отладка превращаются в пытку, поскольку всякий раз, когда я получаю ошибку или неожиданное поведение, у меня нет ни малейшего представления, где искать. В некоторых редких случаях помогает комбинация клавиш Ctrl + F в решении, но в большинстве случаев мне нужно либо спросить старшего, либо использовать метод try & error. Во многих случаях нет способа проверить, работает ли он безопасно и хорошо, тестеры и клиенты, к сожалению, должны это проверить.

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

Является ли этот динамический подход к запросам стандартной практикой в ​​бизнес-приложениях? Мне лично это довольно неудобно.

Ответы [ 7 ]

2 голосов
/ 16 марта 2009

Если это кошмар для отладки, то у вас уже есть ответ: это не лучшая практика, и в будущем следует избегать такой схемы.

Что бы ни стоило, динамический SQL - не обязательно плохая вещь, и он чрезвычайно распространен в больших бизнес-приложениях. Когда все сделано правильно, это может улучшить удобство сопровождения кода:

  • Большинство ORM, таких как Hibernate, делают доступ к базе данных прозрачным для программиста. Например, когда вы запрашиваете объект типа User.GetByID(12), ORM будет динамически создавать SQL, выполнять его, сопоставлять поля с вашим объектом и возвращать его. Как программист, высвобождается огромное количество вашего времени, потому что вам больше не нужно писать SQL-запросы, вы можете просто сосредоточиться на написании своего приложения. Вы можете запрашивать базу данных, не видя, не касаясь и не нюхая жестко запрограммированную строку SQL в любом месте вашего приложения, так что вы сохраняете жесткое разделение между бизнес-логикой и уровнем доступа к данным без написания хранимых процедур.

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

  • Я видел приложения, которые содержат 1000 хранимых процедур, представляющих тривиальные запросы (то есть простые операции выбора, вставки, обновления и удаления). Поддерживать эти базы данных гораздо сложнее, особенно если схема вашей базы данных часто меняется. С хорошо написанным динамическим SQL вы можете представить тысячи эквивалентных запросов всего лишь несколькими функциями (то есть функцией, в которой вы передаете имя таблицы и некоторые параметры). ORM уже предоставляют эту абстракцию для вас, поэтому изменения схемы базы данных не требуют изменений в коде вашего приложения (если, конечно, вы не хотите добавить это новое поле в свой бизнес-объект). Вы можете изменить схему базы данных (добавить новые поля, изменить типы данных столбцов и т. Д.) Без изменения кода приложения или логики доступа к данным.

  • Также есть несколько меньших преимуществ:

    • Независимо от того, какие существуют политики, требующие от программистов или CM копировать хранимые процедуры в систему контроля версий, мы забываем. Если SQL создается программно, он всегда находится под контролем исходного кода.
  • Существует множество мифов о преимуществах хранимых процедур по сравнению с динамическим SQL:

Динамический SQL не плохой как таковой , но есть много предупреждающих знаков, указывающих, когда вы делаете это неправильно:

  • Вы должны никогда см. Регулярное выражение для анализа оператора SQL.
  • Вы должны никогда передавать куски SQL на уровень доступа к данным. Например, метод с подписью User GetUser(string whereclause) очень хрупок. Если меняется схема вашей базы данных, меняется и логика вашего приложения.
  • Доступ к данным должен быть безопасным. Вы никогда не должны передавать нетипизированные наборы данных или строки - или, если это так, вам нужно обернуть эти объекты в типизированный объект, прежде чем возвращать их пользователю.
  • Всегда рассматривайте возможность использования существующего ORM перед развертыванием собственного.

Вы, наверное, заметили, что я много говорил об ORM в этом посте. Это потому, что в общем случае жесткое кодирование строк SQL - это плохая вещь . Правильный способ использования динамического SQL - это иметь инструмент, который генерирует SQL на лету, и это именно то, что многие ORM могут и уже делают.

2 голосов
/ 16 марта 2009

Одна из больших проблем, которые я вижу при таком подходе, заключается в том, что нет четкого разделения ответственности. С несколькими слоями, владеющими различными частями логики, которая создает SQL-запрос, у вас есть приложение, которое не будет хорошо масштабироваться и его будет сложно изменить.

1 голос
/ 16 марта 2009

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

1 голос
/ 16 марта 2009

Динамические запросы также могут открыть вас для внедрения SQL. Наличие их в хранимых процедурах с параметрами помогает уменьшить этот риск.

Если вам нужно / нужно делать запросы динамически в коде, я бы посоветовал иметь их все в одном классе данных или аналогичном. Таким образом, все они находятся в одном месте, если необходимы какие-либо изменения, плюс вы можете увидеть, существует ли уже существующий запрос, прежде чем делать новый. Это также поможет, если вам когда-либо понадобится использовать новую базу данных или вы захотите переключиться на хранение процедур, так как все будет заключено в вызовы в одном месте.

0 голосов
/ 16 марта 2009

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

Я думаю, что самая большая дыра в безопасности при использовании динамического SQL заключается в том, что теперь пользовательский интерфейс должен иметь доступ к базовым таблицам. Это означает, что есть пользователь, будь то Windows Authentication или SQL Login, который может испортить базу данных почти без правил, чтобы остановить их. Я даже не могу сосчитать, сколько раз я заходил в новый магазин и обнаружил, что информация для входа в систему была сохранена в файле конфигурации где-то в виде простого текста. Даже когда это не так, разработчики почти всегда знали имя пользователя и пароль для учетной записи.

Большинство нарушений безопасности (по длинному выстрелу) в корпорациях связаны с работой: недовольные сотрудники, люди, которые хотят быстро заработать, продавая SSN, или люди, которые просто не думают, что что-то не так с поиском медицинской информации для своих сотрудников. бывшая девушка из средней школы. Добавьте к этому разработчика, который выпустил «TRUNCATE TABLE», когда он был уверен , что он был на сервере разработки. Кроме того, у вас есть люди, которые входят в систему и добавляют строку в таблицу где-то, чтобы «исправить» проблему, но они не понимают, что всякий раз, когда вы добавляете строку в таблицу X, вам нужно записать строку в таблицу Y. Если бы весь доступ был обеспечен через хранимые процедуры, они бы не смогли этого сделать.

0 голосов
/ 16 марта 2009

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

мой текущий проект использует SP, а моя предыдущая работа использовала hibernate. на текущей работе есть гораздо больше ошибок, многие из которых никогда бы не произошли, если бы мы использовали ORM. также, в проекте SP у нас была ошибка внедрения SQL, которая была в хранимой процедуре. я никогда не сталкивался с проблемой внедрения SQL-кода в кодовую базу, над которой я работал до сих пор :) кажется, что мозг людей просто отключается, когда они начинают писать хранимые процедуры.

почему вы хотите иметь больше ошибок и больше работать, просто чтобы удовлетворить какой-то испорченный религиозный принцип: «мы должны использовать хранимые процедуры».

0 голосов
/ 16 марта 2009

Хранимые процедуры являются обязательными. Здесь действуют два принципа: хорошее проектирование и безопасность

Базы данных не являются ни ООП, ни функциональными языками программирования (хотя они притворяются). Сила базы данных в ее кислотной природе. Чтобы использовать эту мощь, БД действительно нужен свой собственный уровень, чтобы придерживаться этих принципов.

Во-вторых, как уже упоминали другие, атаки с использованием инъекций данных представляют ОГРОМНУЮ угрозу. Когда у вас на линии миллионы долларов, ваши акционеры или клиенты преступно халатно относятся к тому, что такие данные не защищены с помощью хранимых процедур или какого-либо безопасного связывания данных.

Если вы ДОЛЖНЫ динамически создавать запрос, лучший способ сделать его безопасным - разрешить перевод только входных данных в известное целочисленное / перечислимое значение. Нет свободного ввода текста.

Легко нормализовать немного пользовательского ввода и сравнить с известными значениями в массиве. Я обычно делаю это на нескольких слоях, чтобы входные данные проверялись несколько раз и нормализовались несколько раз.

Но снова. Хранимые процедуры являются обязательными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...