带参数的Oledb update-command在access-db上不起作用

时间:2018-10-04 13:42:42

标签: c# oledb oledbparameter

我的C#应用​​程序中有问题。我尝试通过oledb-connection更新访问数据库。

这是表的架构:

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设置MY_COLUMN = @MY_VALUE,其中SOME_COLUMN = @SOME_VALUE

SOME_COLUMN的数据类型为数字,MY_COLUMN的数据类型为备注

两个参数都是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)显示错误)。

Anny建议是什么原因引起的?

1 个答案:

答案 0 :(得分:2)

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

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

Documentation - OleDbCommand.Parameters

  

当CommandType设置为Text时,OLE DB .NET Provider不支持将命名参数传递给SQL语句或OleDbCommand调用的存储过程的命名参数。在这种情况下,必须使用问号(?)占位符。

     

...

     

因此,将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);
}