Можно ли получить анализируемый текст SqlCommand с помощью SqlParameters?

То, что я пытаюсь сделать, это создать произвольную команду sql с параметрами, установить значения и типы параметров, а затем вернуть обработанную команду sql - с включенными параметрами. Я не буду напрямую запускать эту команду в базе данных sql, поэтому подключение не требуется. Поэтому, если я запустил примерную программу ниже, я надеюсь увидеть следующий текст (или что-то подобное):

WITH SomeTable (SomeColumn)
AS
(
    SELECT N':)'
    UNION ALL
    SELECT N'>:o'
    UNION ALL
    SELECT N'^_^'
)
SELECT SomeColumn FROM SomeTable

И пример программы:

using System;
using System.Data;
using System.Data.SqlClient;

namespace DryEraseConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            const string COMMAND_TEXT = @"
WITH SomeTable (SomeColumn)
AS
(
    SELECT N':)'
    UNION ALL
    SELECT N'>:o'
    UNION ALL
    SELECT @Value
)
SELECT SomeColumn FROM SomeTable
";
            SqlCommand cmd = new SqlCommand(COMMAND_TEXT);
            cmd.CommandText = COMMAND_TEXT;
            cmd.Parameters.Add(new SqlParameter
            {
                ParameterName = "@Value",
                Size = 128,
                SqlDbType = SqlDbType.NVarChar,
                Value = "^_^"
            });
            Console.WriteLine(cmd.CommandText);
            Console.ReadKey();
        }
    }
}

Является ли это достижимым, используя стандартные библиотеки .net? Первоначальный поиск говорит "нет", но я надеюсь, что ошибаюсь.

Ответы

Ответ 1

У вас ошибочное представление о том, как работают параметризованные запросы. "Разбор текста", о котором вы говорите, никогда не создается, и значения параметров никогда не подставляются непосредственно в строку запроса.

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

Что это значит, если у вас есть CommandText, как это:

SELECT SomeColumn FROM SomeTable WHERE ID= @ID

вместо того, чтобы в конечном счете выполнить запрос, который выглядит так:

SELECT SomeColumn FROM SomeTable WHERE ID= 123

на самом деле вы запускаете нечто подобное:

DECLARE @ID Int
Set @ID = RetrieveQueryDataItem("@ID")
SELECT SomeColumn FROM SomeTable WHERE ID= @ID

Теперь это не совсем то, что происходит; двигатель не преобразует такой код. Вместо этого он использует процедуру sp_executesql. Но это должно помочь вам понять, что происходит.

Ответ 2

Joel Coehoorn прав, это не просто простая замена строки или escape-символ, и т.д.

Однако вы можете просмотреть свои параметры, чтобы узнать, соответствуют ли ваши значения:

foreach (IDataParameter i in cmd.Parameters)
{
    Console.WriteLine(i.Value.ToString());
}

Ответ 3

Объект SQLCommand не заменяет параметры для значения в тексте команды и запускает это. Он вызывает sp_execute sql с точным текстом, который вы поставляете, а затем поставляет список параметров. Используйте профилировщик SQL для базы данных, и вы увидите, что я имею в виду.

Что вы на самом деле пытаетесь достичь здесь?

Ответ 4

У меня возникло бы желание изучить LINQ, поскольку он даст вам элемент управления, который вы хотите в коде С#.