Команда обновления 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);
}