Reputation: 15
I'd like to be able to retrieve the return value from a function in Oracle with c#. Currently, this is what I have:
For SQL:
FUNCTION add_resource (
project_view BOOLEAN,
project_id NUMBER,
worker_id NUMBER,
role_id NUMBER) RETURN NUMBER IS
resource_id NUMBER;
BEGIN
INSERT INTO RESOURCE_T (WORKERID, ROLEID, PROJECTID)
VALUES (worker_id, role_id, project_id)
RETURNING RESOURCEID INTO resource_id;
RETURN resource_id;
END add_resource;
For C#
cmdText = "DECLARE resource_id NUMBER; BEGIN resource_id := PKG_RAP.add_resource(" + projectView + "," + id + "," + record["WORKERID"] + "," + record["ROLEID"] + "); END;";
using (OracleCommand cmd = new OracleCommand(cmdText, conn))
{
OracleTransaction trans = conn.BeginTransaction();
try
{
OracleParameter prm = new OracleParameter("resource_id", OracleDbType.Int32, ParameterDirection.ReturnValue);
cmd.Parameters.Add(prm);
cmd.ExecuteNonQuery();
trans.Commit();
}catch
{
trans.Rollback();
throw;
}
}
The query works individually when I test it out in the database, however, the c# is not able to grab the value for resource_id and only gets "null". Any tips would be appreciated!
Upvotes: 1
Views: 1604
Reputation: 59446
The command text must be like this one if you like to call a function (and if you want or have to avoid select ... from dual
:
cmdText = "BEGIN :resource_id := PKG_RAP.add_resource(" + projectView + "," + id + "," + record["WORKERID"] + "," + record["ROLEID"] + "); END;";
As John Pederson already answered, all parameters should be defined as bind values, e.i.
cmdText = "BEGIN :resource_id := PKG_RAP.add_resource(:projectView, :projectId, :workerId, :roleId); END;";
However, I don't think you can use boolean variables when calling from C#. You have to cast it, e.g. to "0" and "1"
Upvotes: 1
Reputation: 189
Does something like this not work?
cmdText = @"select PKG_RAP.add_resource(:projectView, :projectId, :workerId, :roleId) from dual";
using (var cmd = new OracleCommand(cmdText, conn))
using (cmd.Parameters.Add(":projectView", projectView))
using (cmd.Parameters.Add(":projectId", id))
using (cmd.Parameters.Add(":workerId", record["WORKERID"]))
using (cmd.Parameters.Add(":roleId", record["ROLEID"]))
using (var tx = conn.BeginTransaction()) {
try {
// resource ID
var resourceId = Convert.ToInt32(cmd.ExecuteScalar());
tx.Commit();
return resourceId;
} catch {
tx.Rollback();
throw;
}
}
This seems (to me) like the simplest solution to calling a PL-SQL function to return a single value.
ETA: I don't have sufficient rep to comment, yet, but Marc, above, means that you don't return anything in the PL-SQL block you are executing.
Upvotes: 2