OleDbParameters和参数名称

11

我有一条SQL语句通过OleDb执行,语句大致如下:

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);

我的问题是,如果我颠倒命令的参数顺序,那么列中会填充错误的值(例如,名字会填到了部门列而反之亦然)。

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

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

2个回答

16
问题是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());
    }
}

6

SQL支持系统中的参数名称是通用的(即不特定于OleDb)。很多情况下,只有OleDb / Odbc不使用它们。它们存在是因为OleDb是通用基类的具体实现。


有点烦人,好吧,必须修改代码以按正确顺序添加值,谢谢。 - Gaz
这真的非常烦人。说真的,如果你尝试使用ODBC,我想你会遇到参数名称为“?”之类的问题(很久以前的事了);) - TomTom
很奇怪,因为DbParameter没有ParameterName字段 - 如果OleDbParameter不使用ParameterName,那么他们不会将其添加到类中。 - BlueRaja - Danny Pflughoeft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接