11

我有一个通过 OleDb 执行的 SQL 语句,该语句是这样的:

INSERT INTO mytable (name, dept) VALUES (@name, @dept);

我正在向 OleDbCommand 添加参数,如下所示:

OleDbCommand Command = new OleDbCommand();
Command.Connection = Connection;

OleDbParameter Parameter1 = new OleDbParameter();
Parameter1.OleDbType = OleDbType.VarChar;
Parameter1.ParamterName = "@name";
Parameter1.Value = "Bob";

OleDbParameter Parameter2 = new OleDbParameter();
Parameter2.OleDbType = OleDbType.VarChar;
Parameter2.ParamterName = "@dept";
Parameter2.Value = "ADept";

Command.Parameters.Add(Parameter1);
Command.Parameters.Add(Parameter2);

我遇到的问题是,如果我将参数添加到相反的命令中,那么这些列将填充错误的值(即名称在 dept 列中,反之亦然)

Command.Parameters.Add(Parameter2);
Command.Parameters.Add(Parameter1);

我的问题是,如果参数值只是按照添加命令的顺序插入到表中,那么参数名称的意义何在?参数名称似乎是多余的?

4

2 回答 2

15

问题是 OleDb(和 Odbc 也是)不支持命名参数。
它只支持所谓的位置参数。

换句话说:您在将参数添加到命令参数列表时为其提供的名称无关紧要。它仅由 OleDbCommand 类在内部使用,因此它可以区分和引用参数。

重要的是您将参数添加到列表中的顺序。它必须与 SQL 语句中通过问号字符 ( ?) 引用的参数的顺序相同。

但这里有一个解决方案,允许您在 SQL 语句中使用命名参数。它基本上用问号替换 SQL 语句中的所有参数引用,并相应地重新排序参数列表。OdbcCommand 类的工作方式相同,您只需在代码中将“OleDb”替换为“Odbc”即可。

使用如下代码:

command.CommandText = "SELECT * FROM Contact WHERE FirstName = @FirstName";
command.Parameters.AddWithValue("@FirstName", "Mike");
command.ConvertNamedParametersToPositionalParameters();

这是代码

public static class OleDbCommandExtensions
{
    public static void ConvertNamedParametersToPositionalParameters(this OleDbCommand command)
    {
        //1. Find all occurrences of parameter references in the SQL statement (such as @MyParameter).
        //2. Find the corresponding parameter in the commands parameters list.
        //3. Add the found parameter to the newParameters list and replace the parameter reference in the SQL with a question mark (?).
        //4. Replace the commands parameters list with the newParameters list.

        var newParameters = new List<OleDbParameter>();

        command.CommandText = Regex.Replace(command.CommandText, "(@\\w*)", match =>
        {
            var parameter = command.Parameters.OfType<OleDbParameter>().FirstOrDefault(a => a.ParameterName == match.Groups[1].Value);
            if (parameter != null)
            {
                var parameterIndex = newParameters.Count;

                var newParameter = command.CreateParameter();
                newParameter.OleDbType = parameter.OleDbType;
                newParameter.ParameterName = "@parameter" + parameterIndex.ToString();
                newParameter.Value = parameter.Value;

                newParameters.Add(newParameter);
            }

            return "?";
        });

        command.Parameters.Clear();
        command.Parameters.AddRange(newParameters.ToArray());
    }
}
于 2014-02-21T05:19:39.213 回答
6

参数 NAMES 在 SQL 支持系统中是通用的(即不是 OleDb 特定的)。几乎只有 OleDb / Odbc 不使用它们。它们在那里是因为 OleDb 是通用基类的特定实现。

于 2010-03-09T08:59:39.237 回答