Blue Theme Orange Theme Green Theme Red Theme
 
MindFusion's Components
Home | Forums | Videos | Photos | Downloads | Blogs | Interviews | Jobs | Beginners | Training
 | Consulting  
Submit an Article Submit a Blog 
 Login Close
User Id:
Password:
 
Forgot Password
Forgot Username
Why Register
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
World Class ASP.NET Hosting – Click Here for 3 Months Free/NO Setup Fee!
 Resources  
Close
 Our Network  
Close
Search :       Advanced Search »
Home » ADO.NET & Database » Calling Oracle stored procedures from Microsoft.NET

Calling Oracle stored procedures from Microsoft.NET

This article is intended to illustrate how to illustrate how to call Oracle stored procedures and functions from Microsoft.NET through the Microsoft.NET Oracle provider and its object model residing in the namespace System.Data.OracleClient. I will cover several possible scenarios with advanced examples.

Author Rank:
Total page views :  75542
Total downloads : 
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
 
Become a Sponsor

Introduction

This article is intended to illustrate how to illustrate how to call Oracle stored procedures and functions from Microsoft.NET through the Microsoft.NET Oracle provider and its object model residing in the namespace System.Data.OracleClient. I will cover several possible scenarios with advanced examples.

Executing a stored procedure

Let's begin with definitions. A procedure is a module that performs one or more actions. A function is a module that returns a value and unlike procedures a call to a function can exist only as part of an executable such as an element in an expression or the value assigned as default in a declaration of a variable.

The first example illustrates how to call an Oracle procedure passing input parameters and retrieving value by output parameters. For all the examples, we're going to use the default database ORCL which comes with the Oracle database installation. The following code in Listing 1 shows how to create a procedure named count_emp_by_dept which receives as its input parameter the department number and sends as its output parameter the number of employees in this department.

create or replace procedure count_emp_by_dept(pin_deptno number, pout_count out number)
is
begin
 select
count(*) into pout_count
 from scott.emp
 where deptno=pin_deptno;
end count_emp_by_dept;


Listing 1: Creating the procedure  count_emp_by_dept.

Now let's create a console application and add a reference to the assembly System.Data.OracleClient.dll to your project.

The code for this example is illustrated in Listing 2. The first thing to do is to import the object's class residing in the namespace System.Data.OracleClient with the using directive. Then you must set up the parameters and finally call the procedure using ExecuteNonQuery method of the OracleCommand object.

Using System;

using System.Collections.Generic;

using System.Text;

using System.Data.OracleClient;

using System.Data;

 

namespace CallingOracleStoredProc

{

    class Program

    {

        static void Main(string[] args)

        {

            using (OracleConnection objConn = new OracleConnection("Data Source=ORCL; User ID=scott; Password=tiger"))

            {

                OracleCommand objCmd = new OracleCommand();

                objCmd.Connection = objConn;

                objCmd.CommandText = "count_emp_by_dept";

                objCmd.CommandType = CommandType.StoredProcedure;

                objCmd.Parameters.Add("pin_deptno", OracleType.Number).Value = 20;

                objCmd.Parameters.Add("pout_count", OracleType.Number).Direction = ParameterDirection.Output;

 

                try

                {

                    objConn.Open();

                    objCmd.ExecuteNonQuery();

                    System.Console.WriteLine("Number of employees in department 20 is {0}", objCmd.Parameters["pout_count"].Value);

                }

                catch (Exception ex)

                {

                    System.Console.WriteLine("Exception: {0}",ex.ToString());

                }

 

                objConn.Close();

            }

        }

    }

}

Listing 2: The application code calling the stored procedure.

Executing a function

As function is similar to procedures except they return a value, we need to set up a return parameter. Let's see the example.

The following code in Listing 3 shows how to create a function named get_count_emp_by_dept which receives as its input parameter the department number and returns the number of employees in this department. It's very similar to the former procedure in the previous section.

create or replace function get_count_emp_by_dept(pin_deptno number)
 return number
is
 
var_count number;
begin
 select
count(*) into var_count
 from scott.emp
 where deptno=pin_deptno;
 return
var_count;
end get_count_emp_by_dept;

Listing 3: Creating an Oracle function.

Now let's see in the Listing 4 the application code which calls the function. As you can see, we need to define a return parameter to get the returned value. The other part of the code is similar for calling a procedure.

using System;

using System.Collections.Generic;

using System.Text;

using System.Data.OracleClient;

using System.Data;

 

namespace CallingOracleStoredProc

{

    class Program

    {

        static void Main(string[] args)

        {

            using (OracleConnection objConn = new OracleConnection("Data Source=ORCL; User ID=scott; Password=tiger"))

            {

                OracleCommand objCmd = new OracleCommand();

                objCmd.Connection = objConn;

                objCmd.CommandText = "get_count_emp_by_dept";

                objCmd.CommandType = CommandType.StoredProcedure;

                objCmd.Parameters.Add("pin_deptno", OracleType.Number).Value = 20;

                objCmd.Parameters.Add("return_value", OracleType.Number).Direction = ParameterDirection.ReturnValue;

 

                try

                {

                    objConn.Open();

                    objCmd.ExecuteNonQuery();

                    System.Console.WriteLine("Number of employees in department 20 is {0}", objCmd.Parameters["return_value"].Value);

                }

                catch (Exception ex)

                {

                    System.Console.WriteLine("Exception: {0}",ex.ToString());

                }

 

                objConn.Close();

            }

        }

    }

}

Listing 4: The application code calling the function.

Working with cursors

You can use the REF CURSOR data type to work with Oracle result set. To retrieve the result set, you must define a REF CURSOR output parameter in a procedure or a function to pass the cursor back to your application.

Now we're going to define a procedure which opens and sends a cursor variable to our application.

Let's define the package and procedure header as shown in Listing 5.

create or replace package human_resources
as
 type t_cursor is ref cursor;
 procedure
get_employee(cur_employees out t_cursor);
end human_resources;

Listing 5: Creation of the package human_resources and the procedure get_employee.

And now the package definition as shown in Listing 6.

create or replace package body human_resources
as
 procedure
get_employee(cur_employees out t_cursor)
 is
 begin
  open
cur_employees for select * from emp;
 end get_employee;
end human_resources;

Listing 6. The creation of the package body.

Now let's see in Listing 7 the application code calling the procedure inside the package. See the name syntax for calling the procedure contained within a package [package_name].[procedure_name]. In order to get a cursor, you need to define a cursor parameter with the ParameterDirection set up to Output and finally call the ExecuteReader method in the OracleCommand instance.

Using System;

using System.Collections.Generic;

using System.Text;

using System.Data.OracleClient;

using System.Data;

 

namespace CallingOracleStoredProc

{

    class Program

    {

        private static void prvPrintReader(OracleDataReader objReader)

        {

            for (int i = 0; i < objReader.FieldCount; i++)

            {

                System.Console.Write("{0}\t",objReader.GetName(i));

            }

            System.Console.Write("\n");

 

            while (objReader.Read())

            {

                for (int i = 0; i < objReader.FieldCount; i++)

                {

                    System.Console.Write("{0}\t", objReader[i].ToString());

                }

                System.Console.Write("\n");

            }

        }

 

        static void Main(string[] args)

        {

            using (OracleConnection objConn = new OracleConnection("Data Source=ORCL; User ID=scott; Password=tiger"))

            {

                OracleCommand objCmd = new OracleCommand();

                objCmd.Connection = objConn;

                objCmd.CommandText = "human_resources.get_employee";

                objCmd.CommandType = CommandType.StoredProcedure;

                objCmd.Parameters.Add("cur_employees", OracleType.Cursor).Direction = ParameterDirection.Output;

 

                try

                {

                    objConn.Open();

                    OracleDataReader objReader = objCmd.ExecuteReader();

                    prvPrintReader(objReader);

                }

                catch (Exception ex)

                {

                    System.Console.WriteLine("Exception: {0}",ex.ToString());

                }

 

                objConn.Close();

            }

        }

 

    }

}

Listing 7: The application code.

If the procedure returns more than one cursor, the DataReader object accesses them by calling the NextResult method to advance the next cursor.

Let's see the following example.

Listing 8 shows how to create the package header.

create or replace package human_resources
as
 type t_cursor is ref cursor;
 procedure
get_employee_department(cur_employees out t_cursor, cur_departments out t_cursor);
end human_resources;

Listing 8: Package reader.

The package body is shown in Listing 9.

create or replace package body human_resources
as
 procedure
get_employee_department(cur_employees out t_cursor, cur_departments out t_cursor)
 is
 begin
  open
cur_employees for select * from emp;
  open
cur_departments for select * from dept;
 end
get_employee_department;
end human_resources;

Listing 9: Creation of the package body.

Let's see the application code in Listing 10.

using System;

using System.Collections.Generic;

using System.Text;

using System.Data.OracleClient;

using System.Data;

 

namespace CallingOracleStoredProc

{

    class Program

    {

        private static void prvPrintReader(OracleDataReader objReader)

        {

            for (int i = 0; i < objReader.FieldCount; i++)

            {

                System.Console.Write("{0}\t",objReader.GetName(i));

            }

            System.Console.Write("\n");

 

            while (objReader.Read())

            {

                for (int i = 0; i < objReader.FieldCount; i++)

                {

                    System.Console.Write("{0}\t", objReader[i].ToString());

                }

                System.Console.Write("\n");

            }

        }

 

        static void Main(string[] args)

        {

            using (OracleConnection objConn = new OracleConnection("Data Source=ORCL; User ID=scott; Password=tiger"))

            {

                OracleCommand objCmd = new OracleCommand();

                objCmd.Connection = objConn;

                objCmd.CommandText = "human_resources.get_employee_department";

                objCmd.CommandType = CommandType.StoredProcedure;

                objCmd.Parameters.Add("cur_employees", OracleType.Cursor).Direction = ParameterDirection.Output;

                objCmd.Parameters.Add("cur_departments", OracleType.Cursor).Direction = ParameterDirection.Output;

 

                try

                {

                    objConn.Open();

                    OracleDataReader objReader = objCmd.ExecuteReader();

                    prvPrintReader(objReader);

                    objReader.NextResult();

                    prvPrintReader(objReader);

                }

                catch (Exception ex)

                {

                    System.Console.WriteLine("Exception: {0}",ex.ToString());

                }

 

                objConn.Close();

            }

        }

 

    }

}


Listing 10: The application code.

Working with DataSet and DataAdapter

The final example shows how to fill and update a DataSet object through a DataAdapter object.

The first thing to do is create four CRUD procedure to the emp table.  Listing 11 shows how to create the package header.

create or replace package human_resources
as
 
type t_cursor is ref cursor;
 procedure
select_employee(cur_employees out t_cursor);
 procedure insert_employee(p_empno number, p_ename varchar2, p_job varchar2, p_mgr number, p_hiredate date, p_sal number, p_comm number, p_deptno number);
 procedure update_employee(p_empno number, p_ename varchar2, p_job varchar2, p_mgr number, p_hiredate date, p_sal number, p_comm number, p_deptno number);
 procedure delete_employee(p_empno number);
end
human_resources;

Listing 11: The creation of the package header.

Now let's define the package body as shown in Listing 12

create or replace package body human_resources
as
 procedure
select_employee(cur_employees out t_cursor)
 is
 begin
   open
cur_employees for select empno, ename, job, mgr, hiredate, sal, comm, deptno from emp;
 end select_employee;
 procedure insert_employee(p_empno number, p_ename varchar2, p_job varchar2, p_mgr number, p_hiredate date, p_sal number, p_comm number, p_deptno number)
 is
 begin
   update
emp
   set ename=p_ename, job=p_job, mgr=p_mgr, hiredate=p_hiredate, sal=p_sal, comm=p_comm, deptno=p_deptno
   where empno=p_empno;
 end insert_employee;
 procedure update_employee(p_empno number, p_ename varchar2, p_job varchar2, p_mgr number, p_hiredate date, p_sal number, p_comm number, p_deptno number)
 is
 begin
   insert into
emp
   values(p_empno,p_ename,p_job,p_mgr,p_hiredate,p_sal,p_comm,p_deptno);
 end update_employee;
 procedure delete_employee(p_empno number)
 is
 begin
    delete from
emp
    where empno=p_empno;
 end delete_employee;
end human_resources;

Listing 12: The package body creation.

And finally, let's see the application code in Listing 13. As you can see, to fill the data table, we need to define the CRUD (create, read, update, delete) operations through the OracleCommand and associate it to the DataAdapter. I fill the data table, and print out a message with the number of employees so far, and then add a new row representing one employee entity.

using System;

using System.Collections.Generic;

using System.Text;

using System.Data.OracleClient;

using System.Data;

 

namespace CallingOracleStoredProc

{

    class Program

    {

        static void Main(string[] args)

        {

            using (OracleConnection objConn = new OracleConnection("Data Source=ORCL; User ID=scott; Password=tiger"))

            {

                OracleDataAdapter objAdapter = new OracleDataAdapter();

 

                OracleCommand objSelectCmd = new OracleCommand();

                objSelectCmd.Connection = objConn;

                objSelectCmd.CommandText = "human_resources.select_employee";

                objSelectCmd.CommandType = CommandType.StoredProcedure;

                objSelectCmd.Parameters.Add("cur_employees", OracleType.Cursor).Direction = ParameterDirection.Output;

                objAdapter.SelectCommand = objSelectCmd;

 

                OracleCommand objInsertCmd = new OracleCommand();

                objInsertCmd.Connection = objConn;

                objInsertCmd.CommandText = "human_resources.insert_employee";

                objInsertCmd.CommandType = CommandType.StoredProcedure;

                objInsertCmd.Parameters.Add("p_empno", OracleType.Number, 4, "empno");

                objInsertCmd.Parameters.Add("p_ename", OracleType.VarChar, 10, "ename");

                objInsertCmd.Parameters.Add("p_job", OracleType.VarChar, 9, "job");

                objInsertCmd.Parameters.Add("p_mgr", OracleType.Number, 4, "mgr");

                objInsertCmd.Parameters.Add("p_hiredate", OracleType.DateTime,12, "hiredate");

                objInsertCmd.Parameters.Add("p_sal", OracleType.Number, 7, "sal");

                objInsertCmd.Parameters.Add("p_comm", OracleType.Number, 7, "comm");

                objInsertCmd.Parameters.Add("p_deptno", OracleType.Number, 7, "deptno");

                objAdapter.InsertCommand = objInsertCmd;

 

                OracleCommand objUpdateCmd = new OracleCommand();

                objUpdateCmd.Connection = objConn;

                objUpdateCmd.CommandText = "human_resources.update_employee";

                objUpdateCmd.CommandType = CommandType.StoredProcedure;

                objUpdateCmd.Parameters.Add("p_empno", OracleType.Number, 4, "empno");

                objUpdateCmd.Parameters.Add("p_ename", OracleType.VarChar, 10, "ename");

                objUpdateCmd.Parameters.Add("p_job", OracleType.VarChar, 9, "job");

                objUpdateCmd.Parameters.Add("p_mgr", OracleType.Number, 4, "mgr");

                objUpdateCmd.Parameters.Add("p_hiredate", OracleType.DateTime, 10, "hiredate");

                objUpdateCmd.Parameters.Add("p_sal", OracleType.Number, 7, "sal");

                objUpdateCmd.Parameters.Add("p_comm", OracleType.Number, 7, "comm");

                objUpdateCmd.Parameters.Add("p_deptno", OracleType.Number, 7, "deptno");

                objAdapter.UpdateCommand = objUpdateCmd;

 

                OracleCommand objDeleteCmd = new OracleCommand();

                objDeleteCmd.Connection = objConn;

                objDeleteCmd.CommandText = "human_resources.delete_employee";

                objDeleteCmd.CommandType = CommandType.StoredProcedure;

                objDeleteCmd.Parameters.Add("p_empno", OracleType.Number, 4, "empno");

                objAdapter.DeleteCommand = objDeleteCmd;

 

                try

                {

                    DataTable dtEmp = new DataTable();

                    objAdapter.Fill(dtEmp);

 

                    System.Console.WriteLine("Employee count = {0}", dtEmp.Rows.Count );

                    dtEmp.Rows.Add(7935, "John", "Manager", 7782, DateTime.Now,1300,0,10);

 

                    objAdapter.Update(dtEmp);

 

                }

                catch (Exception ex)

                {

                    System.Console.WriteLine("Exception: {0}",ex.ToString());

                }

 

                objConn.Close();

            }

        }

 

    }

}

Listing 12: The application code.

Conclusion

In this article I explained in an extensive way how to access Oracle procedures and functions using Microsoft.NET. I tried to cover all the possible scenario of one .NET application consuming the data provided by stored procedures in Oracle databases.


Login to add your contents and source code to this article
 About the author
 
John Charles Olamendy
He’s a senior Integration Solutions Architect and Consultant. His primary area of involvement is in Object-Oriented Analysis and Design, Database design , Enterprise Application Integration, Unified Modeling Language, Design Patterns and Software Development Process. He has knowledge and extensive experience in the development of Enterprise Applications using Microsoft.NET and J2EE technologies and standards. He is proficient with distributed systems programming; and business-process integration and messaging using the principles of the Services Oriented Architecture (SOA) and related technologies such as Microsoft BizTalk Server, Web Services (Windows Communication Foundation, WSE, BEA WebLogic, Oracle AS and Axis) through multiple implementations of loosely-coupled system. He’s a prolific blogger contributing to .NET and J2EE communities and actively writes articles on subjects relating to integration of applications, business intelligence, and enterprise applications development. He holds a Master’s degree in Business Informatics at Otto Von Guericke University, Magdeburg, Germany. He was recently awarded as MVP. He currently works in the telecommunication industry and delivers integration solutions for this industry. He harbors a true passion for the technology.
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Go.NET
Build custom interactive diagrams, network, workflow editors, flowcharts, or software design tools. Includes many predefined kinds of nodes, links, and basic shapes. Supports layers, scrolling, zooming, selection, drag-and-drop, clipboard, in-place editing, tooltips, grids, printing, overview window, palette. 100% implemented in C# as a managed .NET Control. Document/View/Tool architecture with many properties&events. Optional automatic layout.
Dundas Software
Dundas Chart for .NET is the most advanced .NET charting package available today.  With an extremely complete feature set, elegant architecture and easy implementation, Dundas Chart can quickly add advanced Charting functionality to enhance and transform ASP.NET and Windows Forms applications.  Whether you are implementing charting into internal projects, or building applications for clients, Dundas Chart offers advanced technology and advanced results to get the most out of data.
Clickatell's SMS Gateway
Clickatell's Developer Solutions allow you to SMS enable any website or application via a range of API's. Learn More about our API connections.
Free access to .NET Memory Management video
Everything you need to know about Garbage Collection, Temporary Objects, Fragmentation, Finalization and common causes of memory leaks in .NET. Watch the video here.
Microsoft Visual Studio 2010 Professional
Microsoft Visual Studio 2010 Professional will launch on April 12, but you can beat the rush and secure your copy today by pre-ordering at the affordable estimated retail price of $549 (US). Pre-order now.
Nevron Chart for .NET 2010.1 Now Available
The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
Developer-Ready ASP.NET 2.0 Web Hosting with 3 MONTHS FREE
Now supporting .NET 3.0 Framework with Windows Workflow Foundation, Windows Communication Foundation (WCF), Windows Presentation Foundation (WPF), windows CardSpace (WCS)! Providing more flexibility for Developers with Web Services Support and a User/Permission Manger. Also supporting MS SQL 2005/2000 with Real-Time Backups, FREE Automated Attach .MDF Tool, FREE SQL Restore and Shrink SQL DB Tools, and SQL
 
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
 
 Post a Feedback, Comment, or Question about this article
Subject:  
Comment:  
Become a Sponsor
 Comments
thanks... by kadir On July 13, 2007
thank you for this paper...
Reply | Email | Delete | Modify | 
Re: thanks... by John Charles On August 23, 2007

Hi,

Thanks. I will continue contributing with good articles.

Best regards,

John.

Reply | Email | Delete | Modify | 
Great tutorial by Richard On August 2, 2007
John, This was a very well written tutorial. It really help me a lot. Although I have been programming for a while now. I am new to C# and ASP.NET. I was having a lot of problem figuring out how to call a stored procedure from within a Oracle package. Your article got me back on track. Thanks alot.
Reply | Email | Delete | Modify | 
Re: Great tutorial by John Charles On August 23, 2007

Hi,

Thanks. I will continue writing good article for the community.

Best regards,

John.

Reply | Email | Delete | Modify | 
Stored Procedure Returning Multiple Paramater Types by Holly On September 5, 2007
Thanks for the article. It is the first one I found that addresses the multiple parameters returned. If a call to a stored procedure returns mutliple parameters of different types, say a string and a ref cursor, would the data reader still be the method to access the different parameter values?
Reply | Email | Delete | Modify | 
Re: Stored Procedure Returning Multiple Paramater Types by John Charles On September 7, 2007
Yes.
Reply | Email | Delete | Modify | 
Excellent Post ! by mesegpoint On September 10, 2007
John, nicely covered diff. aspects.
Reply | Email | Delete | Modify | 
Re: Excellent Post ! by John Charles On September 11, 2007

Thanks a lot.

Best regards,

John.

Reply | Email | Delete | Modify | 
Good example by Kornniwat On September 28, 2007

Good example for coding and easy coding from C# to VB.NET.

Thanks & Regards,

Ed.

Reply | Email | Delete | Modify | 
Re: Good example by John Charles On October 9, 2007

Thanks,

John.

Reply | Email | Delete | Modify | 
Boolean Parameters In Oracle Stored Procedures by tomkanary On January 4, 2008
Is there a way to pass Booleans to Oracle stored procedures without getting ORA-06550 error. For example setting OracleParameter.DbType = DbType.Boolean;
Reply | Email | Delete | Modify | 
How to create Package from .NET Application by Jasaz On August 31, 2009
Hi,
   I need to create  a package from C# .NET Application. Execute Non Query works fine. The package too gets created but the Red Cross Appears in the package which disappears when I do Right Click-> Compile. But I need to do the compile the package from .NET Application (i.e. Compilation should follow after I create the package). How do I compile package using C#??
Reply | Email | Delete | Modify | 
how to call stored proc in vb.net by azi On January 16, 2010
my programming display error
Reply | Email | Delete | Modify | 
C and U reverse? by Gino On March 18, 2010
Are the 'C' and 'U' in your CRUD store procedures reverse?

When you call insert_employee proc you perform an update.
And, when you call the update_employee proc you perform an insert. Right?

BTW, nice article!


--gino.d

Reply | Email | Delete | Modify | 

 Hosted by MaximumASP  |  Found a broken link?  |  Contact Us  |  Terms & conditions  |  Privacy Policy  |  Site Map  |  Suggest an Idea  |  Media Kit
Current Version: 5.2009.6.2
 © 2010  contents copyright of their authors. Rest everything copyright Mindcracker. All rights reserved.