带有参数的 Oledb 更新命令不适用于 access-db

Oledb update-command with parameters not working on access-db

我的 C# 应用程序有问题。我尝试通过 oledb 连接更新访问数据库。

这是 table 的架构:

这是我正在使用的函数:

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

命令文本-属性 如下所示:

update MY_TABLE set MY_COLUMN = @MY_VALUE where SOME_COLUMN = @SOME_VALUE

SOME_COLUMN的数据类型是numeric,MY_COLUMN的数据类型是Memo.

两个参数都是oledbtype整型。我尝试将 MY_COLUMN 的参数添加为字符串,因此参数是 VarWChar,但这没有区别。

在 运行 命令之后没有任何反应,没有行被更新。当我在 Access 本身中输入命令文本并执行该语句时。 Access 询问我的参数值。我输入我的值,行得到更新。

为什么这不适用于我的 oledb 连接?


问题似乎出在我正在使用的 SqlContext-class。

使用普通的 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();
    }
}

工作正常...

使用我的 class:

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

没用...

我比较了两个版本的命令文本对象和参数对象,它们是相同的(除了"MY_COLUMN"的值,否则我无法识别行是否更新)。 (我无法添加屏幕截图,因为堆栈溢出显示 "the format is not supported",有趣的是,当我尝试添加第二个屏幕截图(.bmp)时,我能够毫无问题地添加我的第一个屏幕截图(.bmp) ) 显示错误)。

任何建议是什么导致了这个问题?

您的参数顺序不正确。这 2 个循环应按照它们在代码中出现的顺序进行切换。

这很重要,OleDbCommand 不使用命名参数。它们是根据它们在 sql 语句中出现的位置排列的。

Documentation - OleDbCommand.Parameters

The OLE DB .NET Provider does not support named parameters for passing parameters to an SQL statement or a stored procedure called by an OleDbCommand when CommandType is set to Text. In this case, the question mark (?) placeholder must be used.

...

Therefore, the order in which OleDbParameter objects are added to the OleDbParameterCollection must directly correspond to the position of the question mark placeholder for the parameter in the command text


您的代码:

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