Команда обновления Oledb с параметрами, не работающими на access-db

У меня проблема в моем C#-приложении. Я пытаюсь обновить базу данных доступа через oledb-соединение.

Вот схема таблицы:

Вот функция, которую я использую:

public override int Update(string tableName, Action<ISqlParameterizer> actionSqlParameterizerUpdate, Action<ISqlParameterizer> actionSqlParameterizerWhere)
{
    var commandText = $"update {tableName} set @update where @where";

    var whereBuilder = new StringBuilder();
    var updateBuilder = new StringBuilder();
    var whereParameterizer = SqlParameterizer.CreateFrom(this);
    var updateParameterizer = SqlParameterizer.CreateFrom(this);

    actionSqlParameterizerWhere?.Invoke(whereParameterizer);
    actionSqlParameterizerUpdate?.Invoke(updateParameterizer);

    List<IDbDataParameter> parameterList = new List<IDbDataParameter>();

    foreach (var whereParameter in whereParameterizer.GetParameters())
    {
        whereBuilder.Append($" and {whereParameter.ParameterName} = @{whereParameter.ParameterName}");
        parameterList.Add(whereParameter);
    }
    foreach (var updateParameter in updateParameterizer.GetParameters())
    {
        updateBuilder.Append($", {updateParameter.ParameterName} = @{updateParameter.ParameterName}");
        parameterList.Add(updateParameter);
    }

    commandText = commandText.Replace("@where", whereBuilder.ToString().Substring(4));
    commandText = commandText.Replace("@update", updateBuilder.ToString().Substring(1));

    return base.ExecuteNonQuery(commandText, parameterList.ToArray());
}

Свойство commandtext выглядит так:

обновить MY_TABLE установить MY_COLUMN = @MY_VALUE, где SOME_COLUMN = @SOME_VALUE

Тип данных SOME_COLUMN является числовым, тип данных MY_COLUMN - Memo.

Оба параметра являются целыми числами oledbtype. Я попытался добавить параметр для MY_COLUMN в виде строки, поэтому параметр VarWChar, но это не имеет значения.

После выполнения команды ничего не происходит, строки не обновляются. Когда я ввожу текст команды в самом Access и выполняю инструкцию. Доступ запрашивает значения моих параметров. Я ввожу свои значения, и строки обновляются.

Почему это не работает с моим oledb-соединением?


Проблема, кажется, находится в SqlContext-классе, который я использую.

Используя нормальное OleDbConnection:

using (var connection = new OleDbConnection(CONNECTION_STRING_ACCESS))
{
    connection.Open();
    using (var command = connection.CreateCommand())
    {
        command.CommandText = $"UPDATE MY_TABLE SET MY_COLUMN = @MY_VALUE WHERE SOME_COLUMN = @SOME_VALUE";
        command.Parameters.Add(new OleDbParameter("MY_COLUMN", "MY_VALUE"));
        command.Parameters.Add(new OleDbParameter("SOME_COLUMN", 1));
        command.ExecuteNonQuery();
    }
}

работает просто отлично...

Используя мой класс:

using (var accessContext = SqlContext.Create(CONNECTION_STRING_ACCESS, SqlProvider.AccessSql))
{
    accessContext.Update("MY_TABLE", update => {
        update.Add("MY_COLUMN", "MY_VALUE");
    }, where => {
        where.Add("SOME_COLUMN", 1);
    });
}

не работает...

Я сравнил commandtext-objekt и объекты параметров обеих версий, и они одинаковы (за исключением значения "MY_COLUMN", в противном случае я не смог бы распознать, обновляется ли строка). (Я не могу добавить скриншоты, потому что переполнение стека говорит, что "формат не поддерживается", забавно то, что я смог добавить свой первый скриншот (.bmp) без проблем, когда я пытаюсь добавить второй скриншот (.bmp) ошибка показывается).

Любые предложения, что является причиной проблемы?

1 ответ

Решение

Ваши параметры не в правильном порядке. Эти 2 цикла должны быть переключены в порядке их появления в коде.

Это важно, OleDbCommand не использует именованные параметры. Они порядковые в зависимости от позиции, в которой они встречаются в операторе sql.

Документация - OleDbCommand.Parameters

Поставщик OLE DB .NET не поддерживает именованные параметры для передачи параметров в оператор SQL или хранимую процедуру, вызываемую OleDbCommand, если для CommandType задано значение Text. В этом случае необходимо использовать заполнитель вопросительного знака (?).

...

Следовательно, порядок, в котором объекты OleDbParameter добавляются в OleDbParameterCollection, должен напрямую соответствовать позиции заполнителя вопросительного знака для параметра в тексте команды.


Ваш код:

// should occur 2nd
foreach (var whereParameter in whereParameterizer.GetParameters())
{
    whereBuilder.Append($" and {whereParameter.ParameterName} = @{whereParameter.ParameterName}");
    parameterList.Add(whereParameter);
}

// should occur 1st
foreach (var updateParameter in updateParameterizer.GetParameters())
{
    updateBuilder.Append($", {updateParameter.ParameterName} = @{updateParameter.ParameterName}");
    parameterList.Add(updateParameter);
}
Другие вопросы по тегам