Команда обновления Oledb с параметрами, не работающими на access-db - PullRequest
0 голосов
/ 04 октября 2018

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

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

enter image description here

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

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

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

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

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

1 Ответ

0 голосов
/ 04 октября 2018

Ваши параметры не в правильном порядке.Эти 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);
}
...