Существует место для динамического SQL и / или специального SQL, но его необходимо обосновать с учетом конкретных потребностей использования.
Хранимые процедуры, безусловно, являются наилучшей практикой почти во всех ситуациях, и их следует настоятельно рассмотреть в первую очередь.
Эта проблема немного больше, чем просто procs или ad hoc, потому что база данных имеет широкий набор инструментов для определения ее интерфейса, включая таблицы, представления, функции и процедуры.
Люди здесь упоминали о планах выполнения и параметризации, но, безусловно, самое важное, на мой взгляд, заключается в том, что любая техника, которая основывается на открытых базовых таблицах для пользователей, означает, что вы теряете возможность для базы данных изменять свою базовую реализацию или контролировать безопасность вертикально или горизонтально. По крайней мере, я бы раскрыл только представления для типичного приложения / пользователя / роли.
В сценарии, когда приложение или учетная запись пользователя имеют доступ только к SP EXEC SP, тогда у этой учетной записи не будет возможности даже использовать SQL-инъекцию в форме: "; SELECT имя, пароль от ПОЛЬЗОВАТЕЛИ;» или "; УДАЛИТЬ ИЗ ПОЛЬЗОВАТЕЛЕЙ;" или "; DROP TABLE USERS;" потому что в аккаунте нет ничего, кроме EXEC (и, конечно, нет DDL). Вы можете контролировать видимость столбца на уровне SP, и вам не нужно будет, например, отказывать в выборе в столбце зарплаты сотрудника.
Другими словами, если вы не можете свободно предоставлять db_datareader для публики (потому что это действительно то, что вы делаете, когда вы используете LINQ-to-table), тогда вам потребуется некоторая реалистичная защита в вашем приложении, и SP - единственный способ пойти, возможно, с LINQ-to-views.