Я хочу спросить, как другие программисты создают строки динамического SQL для выполнения в качестве CommandText объекта SQLCommand.
Я создаю параметризованные запросы, содержащие сгенерированные пользователем предложения WHERE и поля SELECT. Иногда запросы являются сложными, и мне нужно много контролировать, как строятся различные части.
В настоящее время я использую множество циклов и операторов switch для создания необходимых фрагментов кода SQL и создания необходимых объектов параметров SQL. Этот метод сложен в использовании и делает техническое обслуживание настоящим делом.
Есть ли более чистый и стабильный способ сделать это?
Есть предложения?
EDIT:
Чтобы добавить детали к моему предыдущему сообщению:
- Я не могу шаблонизировать свой запрос из-за требований. Это просто слишком сильно меняется.
- Я должен разрешить агрегатные функции, такие как Count (). Это имеет последствия для условия Group By / Have. Это также вызывает вложенные операторы SELECT. Это, в свою очередь, влияет на имя столбца, используемое
- Некоторые контактные данные хранятся в столбце XML. Пользователи могут запрашивать эти данные AS WELL AS и другие реляционные столбцы вместе. Это приводит к тому, что столбцы xml не могут появляться в предложениях Group By [синтаксис sql].
- Я использую эффективную технику подкачки, которая использует функцию SQL Row_Number (). В результате я должен использовать временную таблицу и затем получить @@ rowcount, прежде чем выбрать мое подмножество, чтобы избежать второго запроса.
Я покажу некоторый код (ужас!), Чтобы вы, ребята, имели представление о том, с чем я имею дело.
sqlCmd.CommandText = "DECLARE @t Table(ContactId int, ROWRANK int" + declare
+ ")INSERT INTO @t(ContactId, ROWRANK" + insertFields + ")"//Insert as few cols a possible
+ "Select ContactID, ROW_NUMBER() OVER (ORDER BY " + sortExpression + " "
+ sortDirection + ") as ROWRANK" // generates a rowrank for each row
+ outerFields
+ " FROM ( SELECT c.id AS ContactID"
+ coreFields
+ from // sometimes different tables are required
+ where + ") T " // user input goes here.
+ groupBy+ " "
+ havingClause //can be empty
+ ";"
+ "select @@rowcount as rCount;" // return 2 recordsets, avoids second query
+ " SELECT " + fields + ",field1,field2" // join onto the other cols n the table
+" FROM @t t INNER JOIN contacts c on t.ContactID = c.id"
+" WHERE ROWRANK BETWEEN " + ((pageIndex * pageSize) + 1) + " AND "
+ ( (pageIndex + 1) * pageSize); // here I select the pages I want
В этом примере я запрашиваю данные XML. Для чисто реляционных данных запрос гораздо проще. Каждая из переменных раздела является StringBuilders. Где пункты построены так:
// Add Parameter to SQL Command
AddParamToSQLCmd(sqlCmd, "@p" + z.ToString(), SqlDbType.VarChar, 50, ParameterDirection.Input, qc.FieldValue);
// Create SQL code Fragment
where.AppendFormat(" {0} {1} {2} @p{3}", qc.BooleanOperator, qc.FieldName, qc.ComparisonOperator, z);