views:

413

answers:

2

We are deploying multiple projects in C# with Oracle databases behind. I would like to implement all of the database logic in Oracle stored procedures as this

  • keeps all of the database logic in the database
  • makes it easier to maintain when database structures change
  • allows re-use of the stored procedures more easily across programming languages

I have test code running where I return rows using a SYS_REFCURSOR and I manually do the data bind on the results as SYS_REFCURSOR could be returning anything - i.e. its not type safe

My question is - is there any way I can define correct types in the stored procedure return type and correctly bind to that type safely in my C# code?

e.g. my PL/SQL procedure looks like this - the return part is not type safe - it could be anything. If I wanted to re-use it from another Oracle package then it will not have the correct type checking

PROCEDURE get_risk (p_process_id IN NUMBER, p_risk OUT sys_refcursor);

and my C# code looks something like the following. I have cludged this together from several classes so hopefully it makes sense. When I extract the data from the DB call I am manually defining the data types - I need to know in the C# code what the Oracle data types are

// setup procedure call
_oracleCommand = new OracleCommand("risk_pkg.get_risk", _conn.OracleConnection);
_oracleCommand.Parameters.Add(new OracleParameter("p_process_id", OracleDbType.Int64, processId, ParameterDirection.Input));
_oracleCommand.Parameters.Add(new OracleParameter("p_risk", OracleDbType.RefCursor, null, ParameterDirection.Output));

_oracleDataAdapter = new OracleDataAdapter(_oracleCommand);
_dataSet = new DataSet();

// call Oracle
_oracleDataAdapter.Fill(_dataSet);

// extract data - hand coded binding
Int64 dbRiskId = (Int64)_dataSet.Tables[0].Rows[0][_dataSet.Tables[0].Columns["risk_id"]];
Int64 dbClientId = (Int64)_dataSet.Tables[0].Rows[0][_dataSet.Tables[0].Columns["client_id"]];

return new Risk(dbRiskId, dbClientId);

This isn't necessarily a problem - I just want to know if there is a better way of doing this to make my PL/SQL more obvious in what it is returning, and making my C# code not have to know the Oracle data types - encapsulating me from database structure changes

Accepted solution : this seems to be the practical solution. I'm still slightly unsatisfied that my Oracle procedure isn't defining its return type explicitly, but that life

+1  A: 

(You should post a sample of your to test code. Because I'm not sure, if I understand your question correctly.)

The returned type is Object to serve any possible return value. You have to convert it manually. But you could generate the code for the conversions. Define a table or a file with this meta information: which stored procedure returns which types and in which .Net types they shall be converted. Use this meta information to create the C# code.

We fill our RefCursors into a DataTable. The code to assign the table fields to their appropriate member variables is generated out of our meta tables.

John Smithers
This could be the way to go - I was looking for some way in which I could completely define the return type in the Oracle procedure. This would make any other code that talks to the procedure type safe as well. I guess the issue I have is that I am not completely defining the interface - I don't normally write functions and return an Object when I know what the data type actually is
Chris Gill
Yes, define that interface. We support Oracle and SQL Server. We have for both one class which cares about db specific stuff. Both are implementing the same interface.
John Smithers
Do you return your data as SYS_REFCURSOR from Oracle?
Chris Gill
No, as Ref Cursor: `TYPE resc IS REF CURSOR;` and `Procedure foo(bla in varchar2, bla2 in char, pResult IN OUT resc)` It wasn't possible to use Sys_refcursor. IIRC because we had to support Oracle 8 which does not support his. But I'm not sure. Do you think it makes a difference?
John Smithers
Not necessarily. Just trying to work out a few more details
Chris Gill
A: 

I have used T4 text templating to do this with SQL server. Works incredibly well.

erikkallen
Any chance of some more information?
Chris Gill