Можно ли получить разобранный текст SqlCommand с помощью SqlParameters? - PullRequest
15 голосов
/ 07 мая 2010

Я пытаюсь создать произвольную команду 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? Первоначальный поиск говорит «нет», но я надеюсь, что ошибаюсь.

Ответы [ 4 ]

22 голосов
/ 07 мая 2010

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

Вот почему так важно использовать параметризованные запросы & mdash; у вас завершено отделение данных запроса от кода запроса. Данные - это данные, код - это код, и они никогда не встретятся. Таким образом, нет возможности для инъекции 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. Но это должно помочь вам понять, что происходит.

3 голосов
/ 07 мая 2010

Джоэл Коухорн прав, это не просто подстановка строк или добавление escape-символов и т. Д.

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

foreach (IDataParameter i in cmd.Parameters)
{
    Console.WriteLine(i.Value.ToString());
}
2 голосов
/ 07 мая 2010

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

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

1 голос
/ 07 мая 2010

Я хотел бы попробовать использовать LINQ , поскольку это даст вам необходимый контроль в вашем коде C #.

...