15

我想要做的是创建一些带有参数的任意 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

4 回答 4

22

您对参数化查询的工作方式有一个错误的概念。您所说的“解析文本”永远不会创建,并且参数值永远不会直接替换到查询字符串中。

这就是为什么使用参数化查询如此重要的原因——您可以将查询数据与查询代码完全隔离。数据就是数据,代码就是代码,两者永远不会相遇。因此,没有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 过程。但这应该可以帮助您了解正在发生的事情。

于 2010-05-07T15:13:25.520 回答
3

Joel Coehoorn 是对的,它不仅仅是简单的字符串替换或转义字符添加等。

但是,您可以查看参数以查看您的值是否符合您的要求:

foreach (IDataParameter i in cmd.Parameters)
{
    Console.WriteLine(i.Value.ToString());
}
于 2010-05-07T15:16:01.973 回答
2

SQLCommand 对象不会将参数换出命令文本中的值并运行它。它使用您提供的确切文本调用 sp_execute sql,然后提供参数列表。对数据库使用 SQL 分析器,你会明白我的意思。

您实际上想在这里实现什么?

于 2010-05-07T15:18:46.583 回答
1

我很想研究使用LINQ,因为它会在 C# 代码中为您提供所需的控制。

于 2010-05-07T15:14:12.973 回答