【摘录】Calling Oracle stored procedures from Microsoft.NET

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.


 1  Using System;
 2 
 3  using  System.Collections.Generic;
 4 
 5  using  System.Text;
 6 
 7  using  System.Data.OracleClient;
 8 
 9  using  System.Data;
10 
11   
12 
13  namespace  CallingOracleStoredProc
14 
15  {
16       class  Program
17 
18      {
19 
20           static   void  Main( string [] args)
21 
22          {
23 
24               using  (OracleConnection objConn  =   new  OracleConnection( " Data Source=ORCL; User ID=scott; Password=tiger " ))
25 
26              {
27 
28                  OracleCommand objCmd  =   new  OracleCommand();
29 
30                  objCmd.Connection  =  objConn;
31 
32                  objCmd.CommandText  =   " count_emp_by_dept " ;
33 
34                  objCmd.CommandType  =  CommandType.StoredProcedure;
35 
36                  objCmd.Parameters.Add( " pin_deptno " , OracleType.Number).Value  =   20 ;
37 
38                  objCmd.Parameters.Add( " pout_count " , OracleType.Number).Direction  =  ParameterDirection.Output;
39 
40                   try
41 
42                  {
43 
44                      objConn.Open();
45 
46                      objCmd.ExecuteNonQuery();
47 
48                      System.Console.WriteLine( " Number of employees in department 20 is {0} " , objCmd.Parameters[ " pout_count " ].Value);
49 
50                  }
51 
52                   catch  (Exception ex)
53 
54                  {
55 
56                      System.Console.WriteLine( " Exception: {0} " ,ex.ToString());
57 
58                  }
59 
60                  objConn.Close();
61 
62              }
63 
64          }
65 
66      }
67 
68  }


 


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.

 1  using  System;
 2 
 3  using  System.Collections.Generic;
 4 
 5  using  System.Text;
 6 
 7  using  System.Data.OracleClient;
 8 
 9  using  System.Data;
10 
11   
12 
13  namespace  CallingOracleStoredProc
14 
15  {
16 
17       class  Program
18 
19      {
20 
21           static   void  Main( string [] args)
22 
23          {
24 
25               using  (OracleConnection objConn  =   new  OracleConnection( " Data Source=ORCL; User ID=scott; Password=tiger " ))
26 
27              {
28 
29                  OracleCommand objCmd  =   new  OracleCommand();
30 
31                  objCmd.Connection  =  objConn;
32 
33                  objCmd.CommandText  =   " get_count_emp_by_dept " ;
34 
35                  objCmd.CommandType  =  CommandType.StoredProcedure;
36 
37                  objCmd.Parameters.Add( " pin_deptno " , OracleType.Number).Value  =   20 ;
38 
39                  objCmd.Parameters.Add( " return_value " , OracleType.Number).Direction  =  ParameterDirection.ReturnValue;
40 
41                   try
42 
43                  {
44 
45                      objConn.Open();
46 
47                      objCmd.ExecuteNonQuery();
48 
49                      System.Console.WriteLine( " Number of employees in department 20 is {0} " , objCmd.Parameters[ " return_value " ].Value);
50 
51                  }
52 
53                   catch  (Exception ex)
54 
55                  {
56 
57                      System.Console.WriteLine( " Exception: {0} " ,ex.ToString());
58 
59                  }
60 
61                  objConn.Close();
62 
63              }
64 
65          }
66 
67      }
68 
69  }


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.

  1  Using System;
  2 
  3  using  System.Collections.Generic;
  4 
  5  using  System.Text;
  6 
  7  using  System.Data.OracleClient;
  8 
  9  using  System.Data;
 10 
 11   
 12 
 13  namespace  CallingOracleStoredProc
 14 
 15  {
 16 
 17       class  Program
 18 
 19      {
 20 
 21           private   static   void  prvPrintReader(OracleDataReader objReader)
 22 
 23          {
 24 
 25               for  ( int  i  =   0 ; i  <  objReader.FieldCount; i ++ )
 26 
 27              {
 28 
 29                  System.Console.Write( " {0}\t " ,objReader.GetName(i));
 30 
 31              }
 32 
 33              System.Console.Write( " \n " );
 34 
 35   
 36 
 37               while  (objReader.Read())
 38 
 39              {
 40 
 41                   for  ( int  i  =   0 ; i  <  objReader.FieldCount; i ++ )
 42 
 43                  {
 44 
 45                      System.Console.Write( " {0}\t " , objReader[i].ToString());
 46 
 47                  }
 48 
 49                  System.Console.Write( " \n " );
 50 
 51              }
 52 
 53          }
 54 
 55   
 56 
 57           static   void  Main( string [] args)
 58 
 59          {
 60 
 61               using  (OracleConnection objConn  =   new  OracleConnection( " Data Source=ORCL; User ID=scott; Password=tiger " ))
 62 
 63              {
 64 
 65                  OracleCommand objCmd  =   new  OracleCommand();
 66 
 67                  objCmd.Connection  =  objConn;
 68 
 69                  objCmd.CommandText  =   " human_resources.get_employee " ;
 70 
 71                  objCmd.CommandType  =  CommandType.StoredProcedure;
 72 
 73                  objCmd.Parameters.Add( " cur_employees " , OracleType.Cursor).Direction  =  ParameterDirection.Output;
 74 
 75                   try
 76 
 77                  {
 78 
 79                      objConn.Open();
 80 
 81                      OracleDataReader objReader  =  objCmd.ExecuteReader();
 82 
 83                      prvPrintReader(objReader);
 84 
 85                  }
 86 
 87                   catch  (Exception ex)
 88 
 89                  {
 90 
 91                      System.Console.WriteLine( " Exception: {0} " ,ex.ToString());
 92 
 93                  }
 94                  objConn.Close();
 95 
 96              }
 97 
 98          }
 99 
100   
101 
102      }
103 
104  }


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.

  1  using  System;
  2 
  3  using  System.Collections.Generic;
  4 
  5  using  System.Text;
  6 
  7  using  System.Data.OracleClient;
  8 
  9  using  System.Data;
 10 
 11   
 12 
 13  namespace  CallingOracleStoredProc
 14 
 15  {
 16 
 17       class  Program
 18 
 19      {
 20 
 21           private   static   void  prvPrintReader(OracleDataReader objReader)
 22 
 23          {
 24 
 25               for  ( int  i  =   0 ; i  <  objReader.FieldCount; i ++ )
 26 
 27              {
 28 
 29                  System.Console.Write( " {0}\t " ,objReader.GetName(i));
 30 
 31              }
 32 
 33              System.Console.Write( " \n " );
 34 
 35   
 36 
 37               while  (objReader.Read())
 38 
 39              {
 40 
 41                   for  ( int  i  =   0 ; i  <  objReader.FieldCount; i ++ )
 42 
 43                  {
 44 
 45                      System.Console.Write( " {0}\t " , objReader[i].ToString());
 46 
 47                  }
 48 
 49                  System.Console.Write( " \n " );
 50 
 51              }
 52 
 53          }
 54 
 55   
 56 
 57           static   void  Main( string [] args)
 58 
 59          {
 60 
 61               using  (OracleConnection objConn  =   new  OracleConnection( " Data Source=ORCL; User ID=scott; Password=tiger " ))
 62 
 63              {
 64 
 65                  OracleCommand objCmd  =   new  OracleCommand();
 66 
 67                  objCmd.Connection  =  objConn;
 68 
 69                  objCmd.CommandText  =   " human_resources.get_employee_department " ;
 70 
 71                  objCmd.CommandType  =  CommandType.StoredProcedure;
 72 
 73                  objCmd.Parameters.Add( " cur_employees " , OracleType.Cursor).Direction  =  ParameterDirection.Output;
 74 
 75                  objCmd.Parameters.Add( " cur_departments " , OracleType.Cursor).Direction  =  ParameterDirection.Output;
 76 
 77   
 78 
 79                   try
 80 
 81                  {
 82 
 83                      objConn.Open();
 84 
 85                      OracleDataReader objReader  =  objCmd.ExecuteReader();
 86 
 87                      prvPrintReader(objReader);
 88 
 89                      objReader.NextResult();
 90 
 91                      prvPrintReader(objReader);
 92 
 93                  }
 94 
 95                   catch  (Exception ex)
 96 
 97                  {
 98 
 99                      System.Console.WriteLine( " Exception: {0} " ,ex.ToString());
100 
101                  }
102 
103                  objConn.Close();
104 
105              }
106 
107          }
108 
109      }
110 
111  }


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.

  1  using  System;
  2 
  3  using  System.Collections.Generic;
  4 
  5  using  System.Text;
  6 
  7  using  System.Data.OracleClient;
  8 
  9  using  System.Data;
 10 
 11   
 12 
 13  namespace  CallingOracleStoredProc
 14 
 15  {
 16 
 17       class  Program
 18 
 19      {
 20 
 21           static   void  Main( string [] args)
 22 
 23          {
 24 
 25               using  (OracleConnection objConn  =   new  OracleConnection( " Data Source=ORCL; User ID=scott; Password=tiger " ))
 26 
 27              {
 28 
 29                  OracleDataAdapter objAdapter  =   new  OracleDataAdapter();
 30 
 31   
 32 
 33                  OracleCommand objSelectCmd  =   new  OracleCommand();
 34 
 35                  objSelectCmd.Connection  =  objConn;
 36 
 37                  objSelectCmd.CommandText  =   " human_resources.select_employee " ;
 38 
 39                  objSelectCmd.CommandType  =  CommandType.StoredProcedure;
 40 
 41                  objSelectCmd.Parameters.Add( " cur_employees " , OracleType.Cursor).Direction  =  ParameterDirection.Output;
 42 
 43                  objAdapter.SelectCommand  =  objSelectCmd;
 44 
 45   
 46 
 47                  OracleCommand objInsertCmd  =   new  OracleCommand();
 48 
 49                  objInsertCmd.Connection  =  objConn;
 50 
 51                  objInsertCmd.CommandText  =   " human_resources.insert_employee " ;
 52 
 53                  objInsertCmd.CommandType  =  CommandType.StoredProcedure;
 54 
 55                  objInsertCmd.Parameters.Add( " p_empno " , OracleType.Number,  4 " empno " );
 56 
 57                  objInsertCmd.Parameters.Add( " p_ename " , OracleType.VarChar,  10 " ename " );
 58 
 59                  objInsertCmd.Parameters.Add( " p_job " , OracleType.VarChar,  9 " job " );
 60 
 61                  objInsertCmd.Parameters.Add( " p_mgr " , OracleType.Number,  4 " mgr " );
 62 
 63                  objInsertCmd.Parameters.Add( " p_hiredate " , OracleType.DateTime, 12 " hiredate " );
 64 
 65                  objInsertCmd.Parameters.Add( " p_sal " , OracleType.Number,  7 " sal " );
 66 
 67                  objInsertCmd.Parameters.Add( " p_comm " , OracleType.Number,  7 " comm " );
 68 
 69                  objInsertCmd.Parameters.Add( " p_deptno " , OracleType.Number,  7 " deptno " );
 70 
 71                  objAdapter.InsertCommand  =  objInsertCmd;
 72 
 73   
 74 
 75                  OracleCommand objUpdateCmd  =   new  OracleCommand();
 76 
 77                  objUpdateCmd.Connection  =  objConn;
 78 
 79                  objUpdateCmd.CommandText  =   " human_resources.update_employee " ;
 80 
 81                  objUpdateCmd.CommandType  =  CommandType.StoredProcedure;
 82 
 83                  objUpdateCmd.Parameters.Add( " p_empno " , OracleType.Number,  4 " empno " );
 84 
 85                  objUpdateCmd.Parameters.Add( " p_ename " , OracleType.VarChar,  10 " ename " );
 86 
 87                  objUpdateCmd.Parameters.Add( " p_job " , OracleType.VarChar,  9 " job " );
 88 
 89                  objUpdateCmd.Parameters.Add( " p_mgr " , OracleType.Number,  4 " mgr " );
 90 
 91                  objUpdateCmd.Parameters.Add( " p_hiredate " , OracleType.DateTime,  10 " hiredate " );
 92 
 93                  objUpdateCmd.Parameters.Add( " p_sal " , OracleType.Number,  7 " sal " );
 94 
 95                  objUpdateCmd.Parameters.Add( " p_comm " , OracleType.Number,  7 " comm " );
 96 
 97                  objUpdateCmd.Parameters.Add( " p_deptno " , OracleType.Number,  7 " deptno " );
 98 
 99                  objAdapter.UpdateCommand  =  objUpdateCmd;
100 
101   
102 
103                  OracleCommand objDeleteCmd  =   new  OracleCommand();
104 
105                  objDeleteCmd.Connection  =  objConn;
106 
107                  objDeleteCmd.CommandText  =   " human_resources.delete_employee " ;
108 
109                  objDeleteCmd.CommandType  =  CommandType.StoredProcedure;
110 
111                  objDeleteCmd.Parameters.Add( " p_empno " , OracleType.Number,  4 " empno " );
112 
113                  objAdapter.DeleteCommand  =  objDeleteCmd;
114 
115   
116 
117                   try
118 
119                  {
120 
121                      DataTable dtEmp  =   new  DataTable();
122 
123                      objAdapter.Fill(dtEmp);
124 
125                      System.Console.WriteLine( " Employee count = {0} " , dtEmp.Rows.Count );
126 
127                      dtEmp.Rows.Add( 7935 " John " " Manager " 7782 , DateTime.Now, 1300 , 0 , 10 );
128 
129                      objAdapter.Update(dtEmp);
130 
131                  }
132 
133                   catch  (Exception ex)
134 
135                  {
136 
137                      System.Console.WriteLine( " Exception: {0} " ,ex.ToString());
138 
139                  }
140 
141                  objConn.Close();
142 
143              }
144 
145          }
146 
147      }
148 
149  }

 

Listing 12: The application code.

你可能感兴趣的:(Microsoft)