Introduction
The issue of using generic oledb.net, odbc.net layers vs. vendor specific providers has always been a debate during the development of data access layers. Second in this series this article will cover the other specific features of oracle database as used by ODP .NET PLEASE VIT My Earlier Article
Making Best Out of Oracle Databases Using Odp.net - Part I
.
Returning Multiple Result Sets from Stored Procedures
It is not uncommon for the front end development teams requesting for result sets from the stored procedures so that they need not concentrate on complex relations. The following code piece will explain one of the different ways to retrieve multiple result sets (cursors) from an odp .NET Client. REF CURSORS ARE VARIABLE CURSORS Using Which Oracle Allow You to Pass The Cursor Locators Between The Applications.
Create or Replace Package Refcurpkg As
TYPE CUR_EMP_T IS REF CURSOR RETURN EMP% RowType;
TYPE CUR_DEPT_T IS REF CURSOR RETURN DEPT% ROWTYPE
Procedure get_cursor (dept_in in number,
CUR_OUT_EMP OUT CUR_EMP_T,
CUR_OUT_DEPT OUT CUR_DEPT_T);
END;
/
Create or Replace Package Body Refcurpkg As
Procedure get_cursor (dept_in in number,
CUR_OUT_EMP OUT CUR_EMP_T,
CUR_OUT_DEPT OUT CUR_DEPT_T) IS
Begin
Open cur_out_emp for select * from EMP
WHERE deptno = dept_in;
Open cur_out_dept for select * from dept;
End GET_CURSOR;
END;
/
.........................
The Following Odp.Net Calls The Stored Procedure and Retrieves The Two Result Sets from it.
OracleCommand cmd = new oracleCommand ();
cmd.commandtext = "refcurpkg.get_cursor";
CMD.CommandType = CommandType.StoredProcedure; cmd.connection = con;
CMD.Parameters.Add ("de PEPT_IN", ORACLEDBTYPE.INT32, DBNULL.VALUE, PARAMETERDIRECTION.INPUT;
Cmd.Parameters.Add ("cur_out_emp", oracledbtype.refcursor, dbnull.value, parameterdirection.output;
Cmd.Parameters.Add ("cur_out_dept", oracledbtype.refcursor, dbnull.value, parameterdirection.output;
cmd.parameters [0] .value = 30;
cmd.executenonquery ();
// read The Employee Result Set
OracleRefcursor ORAREF = (ORACleRefcursor) cmd.Parameters [1] .value;
OracleDataReader Dr = ORAREF.GetDataReader ();
While (Dr.Read ())
{
System.Console.writeline (DR ["ename"]);
}
// read the dept result set
ORAREF = (ORACleRefcursor) cmd.parameters [2] .value;
DR = ORAREF.GetDataReader ();
While (Dr.Read ())
{
System.console.writeline (DR ["DNAME"]);
}
AS Evident from the code piece oraclerefcursor is a corresponding odp.net for the reb. ORACLEREFCURSOR RETURns an ORACLEREFCURSOR RETURns an ORACLEREFCURSOR RETURns an ORACLEREFCURSOR RETURns an ORACLEREFCURSOR RETURNS An OracleDataRead.
Passing C # Array Objects as arguments to stored procedures
Arrays have been a popular data structure in different programming languages, unfortunately arrays have not been directly supported inside databases. However oracle has long been supporting arrays in the form of PL / SQL extensions. This support has been extended to odp.net also. The FOLLOWING Example Shows How you can pass an array object from c # client to an oracle pl / sql stored procedure using odp.net.
THIS SIMPLOYEES AS AN ARRAY AND RETURns The Total Salary for There Employees, Resulting In Less Network Round Trips.
Create or Replace Package ArrayDemo As
Type Emparr_t is Table of Number Index by binary_integer; procedure get_emp_sal_sum (Emparr in Emparr_t, Salsum Out Number);
END;
/
Create or Replace Package Body ArrayDemo AS
Procedure get_emp_sal_sum (Emparr in Emparr_t, Salsum Out Number)
Curemp Emp.EmpnO% TYPE;
CURSAL EMP.SAL% TYPE;
Begin
Salsum: = 0;
For i in 1..Emparr.last
Loop
Begin
CUREMP: = Emparr (i);
SELECT SAL
INTO CURSAL
From EMP
WHERE Empno = CUREMP;
EXCEPTION
When no_data_found
THEN
CURSAL: = 0;
END;
Salsum: = Salsum CURSAL;
End loop;
END GET_EMP_SAL_SUM;
END;
/
The Corresponding C # Client To Pass An Array Will Be as Follows.
OracleCommand cmd = new oracleCommand ("Begin ArrayDemo.get_emp_sal_sum (: 1,: 2); end;", con);
OracleParameter param1 = cmd.parameters.add ("emparr", ORACLEDBTYPE.INT32);
Param1.direction = parameterdirection.input;
Param1.collectionType = OracleCollectionType.plsqlassociativeArray;
PARAM1.VALUE = New Int Int [4] {7900, 7902, 7934, 7788}
PARAM1.SIZE = 4;
OracleParameter Param2 = cmd.Parameters.Add ("Salsum", ORACLEDBTYPE.INT32, PARAMETERDIRECTION.OUTPUT;
cmd.executenonquery ();
System.console.writeline (cmd.parameters [1] .value);
Look at the usage of OracleCollectionType.PLSQLAssociativeArray to indicate the usage of PL / SQL array. Similar concept can be applied in array binding features thru which multiple rows can be inserted into a table in a single round trip.
Lob Support
ODP.net provides the objects OracleClob to access character large object and OracleBlob to access a binary large object stored inside the database. The following example loads a Word Resume into an employee table and then retrieves the same document to create a new word document. Internally Oracleblob is represented as system.byte []. Let us first create a Table in Oracle with a blob column, in this Simple Example Employee's Information Are Stored Along with Their Resume.
CREATE TABLE Empinfo
(
ENO NUMBER (4),
ENAME VARCHAR2 (10),
Resume blob
)
TABLESPACE USERS;
The Following Code Piece Will Create An Employee Record and Will Load A Resume from the local file system.
OracleCommand cmd = new oracleCommand ();
CMD.comMandtext = "Insert Into Empinfo (ENO, ENAME, RESUME) VALUES (: ENO,: ENAME,: RESUME)"
CMD.CONNECTION = con;
Cmd.Parameters.Add (": ENO", ORACLEDBTYPE.INT32);
Cmd.Parameters.Add (": ename", oracledbtype.varchar2);
Cmd.Parameters.Add (": resume", ORACLEDBTYPE.BLOB);
cmd.parameters [0] .value = 100;
cmd.parameters [1] .value = "Will Smith";
System.IO.FileStream Fs =
New system.io.filestream ("c: // files to move // docs // resume.doc",
System.io.filemode.Open, System.IO.FileAccess.read;
Byte [] resbytes = new byte [fs.length];
fs.read (Resbytes, 0, Resbytes.Length);
fs.close ();
CMD.Parameters [2] .value = resbytes;
cmd.executenonquery ();
..................... ..
System.IO.FileStream FW =
New system.io.filestream ("c: // files to move // DOCS // RESUMENEW.DOC",
System.IO.FileMode.create, System.IO.FileAccess.write; binarywriter br = new binarywriter (fw);
cmd.commandtext = "SELECT ENO, ENAME, RESUME FROM Empinfo";
OracleDataReader DR = cmd.executeReader ();
Oracleblob ReadResume = New Oracleblob (Con);
While (Dr.Read ())
{
Console.WriteLine (DR ["ename"]);
ReadResume = Dr.GETORACLEBLOB (2);
}
Br.Write (ReadResume.Value);
Dr.close ();
Conclusion
This section of the series demonstrates further the ability of ODP.net in developing database applications on oracle databases. The features like LOB, multi result sets from stored procedures are certainly essential for any serious database development projects. I will try to cover mode advanced features in the coming articles.