OleDbParameters и имена параметров - PullRequest
10 голосов
/ 09 марта 2010

У меня есть оператор 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);

У меня проблема в том, что если я добавлю параметры для команды в обратном направлении, столбцы заполнятся неправильными значениями (то есть имя находится в столбце dept и наоборот)

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

Мой вопрос: какой смысл в именах параметров, если значения параметров просто вставляются в таблицу в порядке их добавления командой? Имена параметров кажутся избыточными?

Ответы [ 2 ]

11 голосов
/ 21 февраля 2014

Проблема в том, что 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());
    }
}
5 голосов
/ 09 марта 2010

Имена параметров являются общими в системе поддержки SQL (т.е. не являются специфичными для OleDb). Практически ТОЛЬКО OleDb / Odbc НЕ используют их. Они существуют потому, что OleDb - это конкретная реализация базовых базовых классов.

...