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


person Burg    schedule 07.05.2010    source источник


Ответы (4)


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

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

person Joel Coehoorn    schedule 07.05.2010
comment
Спасибо, это именно то, что мне нужно было услышать. Знание того, что sp_executesql вызывается за кулисами, объясняет все. - person Burg; 07.05.2010

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

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

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

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

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

person Ben Robinson    schedule 07.05.2010
comment
Я пытался найти простой способ сгенерировать текст команды sql (эти команды будут выполняться вверх по течению, а не на месте). Функциональность запросов была бы слишком сложной для обработки Linq-To-Sql (не думайте, что LINQ выполняет массовые вставки, T-SQL и тому подобное). Я также надеялся, что смогу избежать подхода StringBuilder. - person Burg; 07.05.2010

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

person kevchadders    schedule 07.05.2010
comment
К сожалению, Linq-To-Sql по большей части является ORM, и я этим не занимаюсь. Что мне нужно сделать, так это продвинутое создание T-SQL (например, массовые вставки). - person Burg; 07.05.2010