简体   繁体   中英

Why doesn't my C# code get a return value from my Oracle function?

I am trying to check if a user is in my database, my return value from my function is either a 't' or an 'f'. as below:

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;

now i call this function with my C# code as below:

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";
    }

when i try this funcion within my oracle developer i get an output. only in my C# code, s always comes out as ""

in my sql developer the following gives me 't'

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

I haven't been working with OracleCommands for a while, but i would suggest this change:

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

The long solution which I bets works (change type to text though):

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

When you have this in your code:

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

It implies, to me, that your command had somethink akin to this:

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

I've never seen a stored procedure use a "returning" as such. That doesn't automatically mean it can't be done, but it doesn't seem consistent with how I've used it and seen it used.

Since you are running a stored proc that returns a scalar value, this would probably suit you better:

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

You need to place the "return value" parameter first in the index, as far as i can tell from working with Oracle it doesn't pass the names of the parameters to the Oracle call, it is absolute placing.

Hope this solves your problems :)

Dom

ParameterDirection.ReturnValue could return only a numeric value, not a string or single char.
(At least in Sql Server). Try to change your function to return an integer and your parameters collection to receive an integer. (I don't have Oracle to test, please correct me if there are some syntax errors)

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...

而不是'返回'语句为什么不声明一个out参数。让我知道如果我不清楚

Just found out this and tested with VS2017 Community edition + 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();
}

使Return_Value您的第一个参数:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM