9

我正在使用System.Data.OracleClientwhich 按名称进行参数绑定,并正在验证 CommandText 和 Parameters 是否同步:

    public string CommandText { get; set; }
    public IEnumerable<OracleParameter> Parameters { get; set; }

    private void VerifyThatAllParametersAreBound()
    {
        var variableNames = Regex.Matches(CommandText, ":\\w+")
            .Cast<Match>().Select(m => m.Value).ToArray();
        var parameteterNames = Parameters.Select(p => p.ParameterName).ToArray();

        var unboundVariables = variableNames.Except(parameteterNames).ToArray();
        if (unboundVariables.Length > 0)
        {
            throw new Exception("Variable in CommandText missing parameter: "
                + string.Join(", ", unboundVariables) + ".");
        }

        var unboundParameters = parameteterNames.Except(variableNames).ToArray();
        if (unboundParameters.Length > 0)
        {
            throw new Exception("Parameter that is not used in CommandText: "
                + string.Join(", ", unboundParameters) + ".");
        }
    }

仍然有一个查询抛出ORA-01008: not all variables bound。当手动将参数值插入有问题的 CommandText 时,查询会运行,因此 CommandText 和参数值应该没问题。我使用 : 作为变量和参数名的前缀,它适用于其他查询。

如何查明此异常的原因?

4

5 回答 5

9

错误是没有为空值指定 DBNull.Value。所以

new OracleParameter(":Foo", item.Foo)

必须以

item.Foo == null 
    ? new OracleParameter(":Foo", DBNull.Value) 
    : new OracleParameter(":Foo", item.Foo)

我认为它在没有空检查的情况下与 ODT.NET 一起工作,但尚未确认。显然System.Data.OracleClient正在删除具有空值的参数。

于 2011-04-18T10:12:14.720 回答
3

如果将null作为参数值传递,则会得到“并非所有变量都绑定”。如果传递DBNull.Value,则会在 OracleClient 的某处出现运行时错误。要传递 NULL,请使用string.Empty,OracleClient 将其转换为任何数据库类型的NULL 。

于 2012-12-06T09:38:02.460 回答
1

如果您有多个参数,则需要将BindByName设置为true。例如:

OracleCommand cmd = con.CreateCommand();

cmd.BindByName = true;

cmd.Parameters.Add(new OracleParameter("parameter1", parameter1));
cmd.Parameters.Add(new OracleParameter("parameter2", parameter2));
于 2019-08-27T15:13:38.030 回答
0

我相信微软在大约 2 年前已弃用OracleClient 作为 ADO.NET 的一部分。

您可能要考虑使用 Oracle 的数据访问组件 (ODAC odp.net)。使用 OracleParameter 类易于构建(和检查计数)参数。设置和安装在此处找到的文档。哦,你也可以进入他们的实体框架(和 LINQ)支持(我认为还是测试版?)。

无论如何都要认真考虑的事情。

于 2011-04-15T16:03:15.740 回答
0

基于上述答案和评论,我确保以下内容来解决此问题:

  • 参数的绑定顺序与它们在查询中出现的顺序相同
  • 指定参数类型
  • 如果 SQL 中多次需要相同的参数值,请在 SQL 中以不同的方式命名每个参数(不确定是否需要)

    OracleParameter[] orclParams = new OracleParameter[] { new OracleParameter{ ParameterName = "param1", OracleDbType = OracleDbType.Varchar2, Value = "abc" }, new OracleParameter{ ParameterName = "param2", OracleDbType = OracleDbType.Varchar2, Value = " abc" }, 新的 OracleParameter{ ParameterName = "date1", OracleDbType = OracleDbType.Date, Value = myDate } }; SomeFunction(sqlQuery, orclParams.ToList());

于 2020-02-07T19:42:15.230 回答