【问题标题】:Why doesn't my C# code get a return value from my Oracle function?为什么我的 C# 代码没有从我的 Oracle 函数中获得返回值?
【发布时间】:2014-08-07 12:02:40
【问题描述】:

我正在尝试检查用户是否在我的数据库中,我的函数返回值是“t”还是“f”。如下:

CREATE OR REPLACE FUNCTION LOGIN
    (p_Naam in varchar2
    ,p_Wachtwoord in varchar2)
    return varchar2
is
    v_count number;
BEGIN
    select count(*) into v_count
    from Lid
    where Naam = p_Naam 
    and Wachtwoord = p_Wachtwoord;
    if v_count > 0 then
        return 't';
    end if;
    return 'f';
END LOGIN;

现在我用我的 C# 代码调用这个函数,如下所示:

public bool LogIn(string gebruikersnaam, string wachtwoord)
    {
        string s;

        var cmd = new OracleCommand
        {
            Connection = conn,
            CommandText = "Login",
            CommandType = CommandType.StoredProcedure
        };

        cmd.Parameters.Add("p_Naam", OracleDbType.Varchar2).Value = gebruikersnaam;
        cmd.Parameters.Add("p_Wachtwoord", OracleDbType.Varchar2).Value = wachtwoord;
        cmd.Parameters.Add("return_value", OracleDbType.Varchar2, ParameterDirection.ReturnValue);

        try
        {
            conn.Open();
            cmd.ExecuteNonQuery();
            s = cmd.Parameters["return_value"].Value.ToString();
        }
        finally
        {
            conn.Close();
        }

        return s == "t";
    }

当我在我的 oracle 开发人员中尝试这个功能时,我得到了一个输出。 仅在我的 C# 代码中,s 总是以 ""

在我的 sql 开发人员中,以下给了我 't'

BEGIN
  dbms_output.put_line(LOGIN('Willem Koonings', 'willem'));
END;

【问题讨论】:

  • 你确定你没有引发任何异常?
  • ParameterDirection.ReturnValue 只能返回数值,不能返回字符串。 (至少在 Sql Server 中)尝试更改您的 proc 以返回一个整数和您的参数集合以接收一个整数。
  • 尝试更改将“return_value”参数添加到cmd.Parameters.Add("return_value", OracleType.VarChar2, 1).Direction = ParameterDirection.ReturnValue; 的语句。在这种情况下,Add 的第三个参数应该是列的大小 - 在这种情况下,您只返回一个字符,所以它应该是 1。ParameterDirection 是参数的一个属性。分享和享受。

标签: c# oracle function stored-procedures


【解决方案1】:

我已经有一段时间没有使用 OracleCommands,但我建议进行此更改:

CommandText = "Login(:p_Naam, :p_Wachtwoord)";

我打赌的长解决方案有效(但将类型更改为文本):

CommandText = "select Login(:p_Naam, :p_Wachtwoord) return_value from dual";

【讨论】:

  • 是也不是...只是在他当前的代码中更改它不会有任何好处;它仍将作为带有CommandType = CommandType.StoredProcedure 的存储过程执行。但是,肯定有理由简单地将其作为选择执行。对于像这样的简单功能,它很可能工作得很好。
【解决方案2】:

当你的代码中有这个时:

s = cmd.Parameters["return_value"].Value.ToString();

对我来说,这意味着你的命令有类似这样的想法:

insert into test (user_name, create_date)
values (:USERNAME, sysdate)
returning user_id into :return_value

我从未见过这样的存储过程使用“返回”。这并不自动意味着它不能完成,但它似乎与我使用它和看到它的使用方式不一致。

由于您正在运行一个返回标量值的存储过程,这可能更适合您:

string result = (string)cmd.ExecuteScalar();

【讨论】:

  • Oracle 使用 PL/SQL 进行高级编程。所以,它有功能。
【解决方案3】:

您需要首先将“返回值”参数放在索引中,据我所知,使用 Oracle 时它不会将参数名称传递给 Oracle 调用,而是绝对放置。

希望这能解决你的问题:)

Dom

【讨论】:

    【解决方案4】:

    ParameterDirection.ReturnValue 只能返回数值,不能返回字符串或单个字符。
    (至少在 Sql Server 中)。尝试更改您的函数以返回一个整数,并将您的参数集合更改为接收一个整数。 (本人没有Oracle测试,如有语法错误请指正)

    See this reference (for Sql Server)

    CREATE OR REPLACE FUNCTION LOGIN
        (p_Naam in varchar2
        ,p_Wachtwoord in varchar2)
        return INTEGER 
    is
        v_count number;
    BEGIN
        select count(*) into v_count
        from Lid
        where Naam = p_Naam 
        and Wachtwoord = p_Wachtwoord;
        if v_count > 0 then
            return 1;
        end if;
        return 0;
    END LOGIN;
    
    ....
    cmd.Parameters.Add("p_Naam", OracleDbType.Varchar2).Value = gebruikersnaam;
    cmd.Parameters.Add("p_Wachtwoord", OracleDbType.Varchar2).Value = wachtwoord;
    cmd.Parameters.Add("return_value", OracleDbType.Int32, ParameterDirection.ReturnValue);
    ....
    
    int result = Convert.ToInt32(cmd.Parameters["return_value"].Value);
    if(result == 0)
       // fail
    else
       // success...
    

    【讨论】:

      【解决方案5】:

      你为什么不声明一个输出参数而不是'Return'语句。如果我不清楚,请告诉我

      【讨论】:

        【解决方案6】:

        刚刚发现这一点并使用 VS2017 社区版 + 11g 进行了测试。

        OracleCommand chkCmd = null;
        try
        {
            chkCmd = new OracleCommand();
            chkCmd.CommandText = "login";
            chkCmd.CommandType = CommandType.StoredProcedure;
        
            chkCmd.Connection = conn;
            OracleParameter mobParam1 = new OracleParameter("p_Naam", OracleDbType.Varchar2, 2000);
            mobParam1.Direction = ParameterDirection.Input;
            mobParam1.Value = gebruikersnaam;
            OracleParameter mobParam2 = new OracleParameter("p_Wachtwoord", OracleDbType.Varchar2, 2000);
            mobParam2.Direction = ParameterDirection.Input;
            mobParam2.Value = wachtwoord;
            OracleParameter retValue = new OracleParameter("returnVal", OracleDbType.Varchar2, 2000);
            retValue.Direction = ParameterDirection.ReturnValue;
        
        
            chkCmd.Parameters.Clear();
            chkCmd.Parameters.Add(retValue);
            chkCmd.Parameters.Add(mobParam1);
            chkCmd.Parameters.Add(mobParam2);
            con.Open();
            chkCmd.ExecuteScalar();
            string retmsg = Convert.ToString(retValue.Value);
        
        
            return retmsg=="t";
        }
        finally 
        {
            con.Close();
            chkCmd.Dispose();
            con.Dispose();
        }
        

        【讨论】:

          【解决方案7】:

          将Return_Value设为您的第一个参数:

          cmd.Parameters.Add("Return_Value", OracleDbType.Boolean, ParameterDirection.ReturnValue);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-09-17
            • 2017-08-22
            • 1970-01-01
            • 2012-09-07
            • 1970-01-01
            • 2018-01-27
            相关资源
            最近更新 更多