【问题标题】:Oracle error: PLS-00306: wrong number or types of argumentsOracle 错误:PLS-00306:参数数量或类型错误
【发布时间】:2015-09-09 07:36:51
【问题描述】:

我正在使用 Dapper 和 ODP.Net 来调用存储过程。 没有发现我的参数有什么问题,我觉得很愚蠢,但它就是这样:

这是存储过程的签名:

PROCEDURE SP_NETWORK_GETALL(UserLogon IN VARCHAR2, NetworkVersionList OUT refCursor)

这是我的 .Net 调用:

using (var conn = new OracleConnection(connString))
{
    var parameters = new List<OracleParameter>
    {
        new OracleParameter()
        {
            Direction = ParameterDirection.Input,
            ParameterName = "UserLogon",
            OracleDbType = OracleDbType.Varchar2,
            Size = 4000,
            Value = "TEST"
        },
        new OracleParameter()
        {
            Direction = ParameterDirection.Output,
            OracleDbType = OracleDbType.RefCursor,
            ParameterName = "NetworkVersionList",
            Value = DBNull.Value
        },
    };

    var results = conn.Query("SDTM.PKG_SP_GET.SP_NETWORK_GETALL", parameters, commandType: CommandType.StoredProcedure);
}

我已经尝试过这个存储过程,它可以工作。我已经将 Dapper 用于其他存储过程,它也可以。我尝试过更改参数的顺序(首先是引用光标),是否设置 VarChar2 参数的大小,是否设置引用光标的 DBNull.Value。

我在 stackoverflow 或互联网上看到过一百万个这样的问题,但我在这里看不到参数不匹配...

【问题讨论】:

  • 是否需要架构名称?
  • 好吧,我只是尝试不使用架构名称,但我得到了同样的错误,所以我认为这不是问题......
  • 这个错误的常见原因是ODP.NET默认是按位置绑定的,而不是按参数名绑定的。这似乎不是这里的问题,但如果您提供给我们的过程不是实际的,请确保您以正确的顺序绑定或将 Bindbyname 设置为 true。接下来,确保“refcursor”是 oracle 类型。我虽然正确的类型是 SYS_Refcursor。如果它实际上是一个用户定义的类型,而不是一个简单的 ref_cursor 你不能像这样绑定。也许您应该向我们提供该过程的实际创建语句。
  • 这篇文章很旧,但你应该看看,看看你在做什么不同。因为你有一个帮助类来绑定和执行,所以很难说你哪里出错了:oracle.com/technetwork/articles/dotnet/…
  • 好吧,我设法做了一些有效的事情。我按照post 的建议创建了一个实现 SqlMapper.IDynamicParameters 的类。它在命令执行之前添加参数。我没有更改参数声明并且它可以工作......我在这里在 ODP.Net 中闻到了一些可疑的东西。如果有人有更好的解决方案,我会保留这个问题......无论如何,谢谢克里斯蒂安

标签: .net oracle stored-procedures dapper odp.net


【解决方案1】:

问题是您将 OracleParameter 对象列表发送到 dapper 的“参数”变量。 Dapper 与提供者无关,您发送的是提供者特定的类型。

看一下 dapper 代码中的 GetCacheInfo 方法,你会看到 dapper 尝试处理参数的三种情况:

  1. IDynamicParameters 的一个对象
  2. IEnumerable 的一个对象>
  3. Default/Else - 尝试在对象中查找与命令中的标记匹配的属性。

您可能陷入了默认情况,但是因为您有一个 proc,所以命令中没有标记,也没有添加任何参数。即使它们是,它也可能会通过 List 类型的属性进行搜索,并且不会找到匹配项。

添加 IDynamicParameters 让您可以控制参数,这就是它起作用的原因。这与 odp.net 无关。

我想这是我对 dapper 和所有 ORM 的不满之一 - 尽管他们会努力尝试,但总会有无法抽象掉的提供者特定的东西。这就是为什么我更喜欢简单地设置提供程序特定的命令,然后使用只进行映射的实用程序类(不关心连接/设置/执行)。

【讨论】:

  • 所以我的实现 SqlMapper.IDynamicParameters 的类是要走的路。看起来很奇怪的是,我之前通过直接发送 OracleParameters 列表将 dapper 与其他存储过程(使用 refCursors、UDT 和其他 oracle 特定的东西)一起使用,并且工作正常。
  • 我想我很想看看一个像你描述的那样有效的案例。甚至可以调试简洁的代码并查看参数是如何添加的。也许有一个我没有看到的分支。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-27
  • 2018-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多