Thanasis Ioannidis
Thanasis Ioannidis

Reputation: 3231

Return an sql variable's value from within an Oracle Sql Query back to .NET code

For the past few hours I am trying to do the simplest of the simple things (at least for SQL SERVER) in an Oracle Data Base, through a .NET application using ADO.NET. It seems impossible.

For SQL SERVER I would do this simple task, supposing I have an SqlCommand object

comm.CommandText = @"
   DECLARE @next_id INT
   SET @next_id = (SELECT ISNULL(MAX(id_col),0) FROM TABLE_1) + 1
   INSERT INTO TABLE_1 (id_col, col1, ...) VALUES (@next_id, val1, ...)
   SELECT @next_id";
int id = Convert.ToInt32(comm.ExecuteScalar());

That would insert a new record to table TABLE_1 and I would take back the new id in the "id" variable in c# code.

Four simple steps

Ok I managed to declare the variable in Oracle query. Also I (think) I managed to give it a value (With SELECT INTO)

How can I get back this variable's value back in c#? How can i SELECT a variable's value to the output stream in Oracle SQL?

I know that there are better ways to achieve getting back an identity column, but that's not the question here. It could be a totally different example. The question is simple.: I have declared a variable inside an oracle sql script that will be executed from within .net app. How can i get the variable's value back to c#, from an oracle query? What is the above code's equivalent with Oracle ADO.NET query?

Upvotes: 3

Views: 9046

Answers (1)

tbone
tbone

Reputation: 15473

You'll want to use ODP.NET (Oracle's Oracle Data Access Components):

An example of this is below. Note that in ODP.NET, you can establish a parameters direction (input, inputoutput, output, returnvalue) to correspond with the parameters of the procedure or statement you're running. In this example, I'm grabbing a returnvalue, which is an ID that is generated by the db via a sequence and trigger (its created automagically as far as the .NET app is concerned):

int event_id = 0;
using (OracleConnection oraConn = new OracleConnection(connStr))
{
    string cmdText = @"insert into EVENT
        (EVENT_NAME, EVENT_DESC)
        values
        (:EVENT_NAME, :EVENT_DESC)
        RETURNING EVENT_ID INTO :EVENT_ID
        ";

    using (OracleCommand cmd = new OracleCommand(cmdText, oraConn))
    {
        oraConn.Open();
        OracleTransaction trans = oraConn.BeginTransaction();
        try
        {
            OracleParameter prm = new OracleParameter();
            cmd.BindByName = true;
            prm = new OracleParameter("EVENT_NAME", OracleDbType.Varchar2); 
            prm.Value = "SOME NAME"; cmd.Parameters.Add(prm);

            prm = new OracleParameter("EVENT_DESC", OracleDbType.Varchar2); 
            prm.Value = "SOME DESC"; cmd.Parameters.Add(prm);

            prm = new OracleParameter( "EVENT_ID"
                                     , OracleDbType.Int32
                                     , ParameterDirection.ReturnValue); 
            cmd.Parameters.Add(prm);

            cmd.ExecuteNonQuery();
            trans.Commit();
            // return value
            event_id = ConvertFromDB<int>(cmd.Parameters["EVENT_ID"].Value);
        }
        catch
        {
            trans.Rollback();
            throw;
        }
        finally
        {
            trans.Dispose();
        }
        oraConn.Close();
    }
} 

The ConvertFromDB is just a generic to cast the return value to its .NET equivalent (an int in this case).

Hope that helps.

EDIT:

You can easily bind an array of values (and retrieve an array of return values) in ODP.NET:

using (OracleConnection oraConn = new OracleConnection(connStr))
{
    string cmdText = @"insert into TEST_EVENT
        (EVENT_NAME, EVENT_DESC)
        values
        (:EVENT_NAME, :EVENT_DESC)
        RETURNING EVENT_ID INTO :EVENT_ID
        ";

    using (OracleCommand cmd = new OracleCommand(cmdText, oraConn))
    {
        oraConn.Open();
        OracleTransaction trans = oraConn.BeginTransaction();
        try
        {
            string[] event_names = new string[2];
            string[] event_descs = new string[2];
            int[] event_ids = new int[2];

            event_names[0] = "Event1";
            event_descs[0] = "Desc1";

            event_names[1] = "Event2";
            event_descs[1] = "Desc2";

            OracleParameter prm = new OracleParameter();
            cmd.Parameters.Clear();
            cmd.ArrayBindCount = 2;
            cmd.BindByName = true;

            prm = new OracleParameter("EVENT_NAME", OracleDbType.Varchar2); 
            prm.Value = event_names; cmd.Parameters.Add(prm);

            prm = new OracleParameter("EVENT_DESC", OracleDbType.Varchar2); 
            prm.Value = event_descs; cmd.Parameters.Add(prm);

            prm = new OracleParameter( "EVENT_ID"
                                     , OracleDbType.Int32
                                     , ParameterDirection.ReturnValue); 
            cmd.Parameters.Add(prm);


            cmd.ExecuteNonQuery();
            trans.Commit();
            // get return values

            event_ids = (int[])(cmd.Parameters["EVENT_ID"].Value);
        }
        catch
        {
            trans.Rollback();
            throw;
        }
        finally
        {
            trans.Dispose();
        }
        oraConn.Close();
    }
}

Upvotes: 4

Related Questions