2015-06-23 425 views
0

我正在使用Dapper和ODP.Net来调用存储过程。 我觉得愚蠢没有发现有什么错我的参数,但这里有云:Oracle错误:PLS-00306:错误的参数数量或类型

这里是存储过程签名:

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。

我已经看到了成千上万个问题是这样一个计算器上或在互联网上,但我不能在这里看到的参数不匹配......

+0

是否需要模式名称? – kevinsky

+0

嗯,我只是尝试没有模式名称,我得到了同样的错误,所以我不认为这是问题... –

+0

这种错误的通常原因是因为ODP.NET默认绑定的位置,而不是参数名称。这似乎不是问题,但为了防止您提供给我们的过程不是真正的过程,请确保按正确顺序绑定或将Bindbyname设置为true。接下来,确保“refcursor”是一个oracle类型。我虽然正确的类型是SYS_Refcursor。如果它实际上是用户定义的类型,而不是简单的ref_cursor,则不能像这样绑定。也许你应该为程序提供实际的创建声明。 –

回答

1

的问题是,你发送列表的OracleParameter反对小巧的“参数”变量。 Dapper意味着与提供者无关,并且您正在发送提供者特定类型。

看看在短小精悍代码的GetCacheInfo方法,你会在方式短小精悍尝试处理参数,请参阅三种情况:

  1. IDynamicParameters的目的
  2. 的IEnumerable <的目的KeyValuePair <字符串,对象>>
  3. 默认值/否 - 试图在您的对象中查找与命令中的令牌相匹配的属性。

您可能会陷入默认情况,但因为您有一个proc,所以命令中没有令牌,也没有添加任何参数。即使他们是,它可能会搜索类型列表<>属性,它不会找到匹配。

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

我想这是我所有的ORM中的一员,尽管他们会尝试一样艰难,但总是会有提供者特定的东西无法被抽象出来。这就是为什么我更喜欢简单地设置特定于提供者的命令,然后使用只进行映射的实用程序类(而不关心连接/设置/执行)。

+0

所以我的类实现SqlMapper.IDynamicParameters是要走的路。然后奇怪的是,我之前用其他存储过程(使用refCursors,UDT和其他特定于oracle的东西)通过直接发送OracleParameters列表来使用dapper,并且它工作正常。 –

+0

我想我会有兴趣看到一个能像你描述的那样工作的案例。也许甚至可以调试到精巧的代码,看看如何添加参数。也许有一个我没有看到的分支。 –

相关问题