この項では、Oracle Data Provider for .NETを.NETストアド・プロシージャ内で使用する際に適用される重要な概念について説明します。
注意: ODP.NET管理対象ドライバは、.NETストアド・プロシージャをサポートしていません。 |
.NETストアド・プロシージャでは、暗黙的なデータベース接続を使用してOracleデータにアクセスできます。暗黙的なデータベース接続が.NETストアド・プロシージャのコール元によりすでに確立されているため、ユーザー接続を確立するかわりに、この暗黙的なデータベース接続を使用する必要があります。これにより、リソースの使用量が最小化されます。
暗黙的なデータベース接続を表すOracleConnection
オブジェクトを.NETストアド・プロシージャで取得するには、OracleConnection
オブジェクトのConnectionString
プロパティを"context
connection=true"
に設定し、Open
メソッドを起動します。"context
connection=true"
は、Statement
Cache
Size
属性以外の接続文字列属性と一緒に使用することはできません。
暗黙的なデータベース接続の可用性は、実行時にOracleConnection.IsAvailable
静的プロパティを使用して確認できます。このプロパティでは、Oracle Data Provider for .NETが.NETストアド・プロシージャで使用されている場合は常にtrue
を戻します。それ以外の場合は、false
が戻されます。
注意: データベース・リンクは、.NETストアド・プロシージャではサポートされません。 |
.NETストアド・プロシージャを起動して使用できる暗黙的なデータベース接続は1つのみです。暗黙的なデータベース接続に加えてさらに接続を確立するには、明示的な接続を作成する必要があります。暗黙的なデータベース接続を表すOracleConnection
に対してClose
メソッドが起動されると、接続は実際にはクローズされません。したがって、同一の、または別のOracleConnection
オブジェクトに対してOpen
メソッドを起動して、暗黙的なデータベース接続を表す接続を取得することができます。
暗黙的なデータベース接続を取得できるのは、最初に.NETストアド・プロシージャを起動した、ネイティブのOracleスレッドでOpen
メソッドを起動するときのみです。ただし、ネイティブのOracleスレッドから生成されたスレッドでは、ネイティブのOracleスレッドにより取得された暗黙的なデータベース接続を使用できます。
暗黙的なデータベース接続では、.NETストアド・プロシージャを実行すると、現在のトランザクションが自動的に継承されます。コンテキスト接続では、明示的なトランザクションは.NETストアド・プロシージャ内で開始、コミット、またはロールバックできませんが、クライアント接続では、明示的なトランザクションは.NETストアド・プロシージャ内で開始、コミット、またはロールバックできます。
たとえば、コンテキスト接続の場合、OracleConnection.BeginTransaction
を.NETストアド・プロシージャ内で使用できませんが、クライアント接続の場合は使用できます。.NETストアド・プロシージャは分散トランザクションをサポートしません。分散トランザクションのクライアント接続に参加して.NETストアド・プロシージャまたはファンクションをコールした場合、エラーが発生します。
トランザクションの一部にする必要があるデータベース上で、.NETストアド・プロシージャまたは関数の操作を実行する場合、このトランザクションは、.NETストアド・プロシージャを呼び出す前に開始する必要があります。必要なコミットまたはロールバックは、.NETストアド・プロシージャや関数から戻された後に実行する必要があります。
次の例は、クライアント・アプリケーションと従業員のレコードをEMP
表に挿入するInsertRecordSP
という.NETストアド・プロシージャで構成されています。
例(.NETストアド・プロシージャ)
using System; using System.Data; using Oracle.DataAccess.Client; // This class represents an Oracle .NET stored procedure that inserts // an employee record into an EMP table of SCOTT schema. public class InsertRecordSP { // This procedure will insert a row into the emp database // For simplicity we are using only two parameters, the rest are hard coded public static void InsertRecord( int EmpNo, string EmpName ) { if(OracleConnection.IsAvailable == true ) { OracleConnection conn = new OracleConnection( "context connection=true"); conn.Open(); // Create new command object from connection context OracleCommand Cmd = conn.CreateCommand(); Cmd.CommandText = "INSERT INTO EMP( EMPNO, ENAME, JOB," + "MGR, HIREDATE, SAL, COMM, DEPTNO ) " + "VALUES ( :1, :2, 'ANALYST', 7566, " + "'06-DEC-04', 5000, 0, 20 )"; Cmd.Parameters.Add( ":1", OracleDbType.Int32, EmpNo, ParameterDirection.Input ); Cmd.Parameters.Add( ":2", OracleDbType.Varchar2, EmpName, ParameterDirection.Input ); Cmd.ExecuteNonQuery(); } } }
例(クライアント・アプリケーション)
この例では、従業員番号7950のBernsteinという新しい従業員をEMP
表に入力します。
// C# // This sample demonstrates how to start the transaction with ODP.NET client // application and execute an Oracle .NET stored procedure that performs // a DML operation. Since .NET stored procedure inherits the current // transaction from the implicit database connection, DML operation // in .NET stored procedure will not be in auto-committed mode. // Therefore, it is up to the client application to do a COMMIT or ROLLBACK // after returning from .NET stored procedure using System; using System.Data; using Oracle.DataAccess.Client; // In this class we are starting a transaction on the client side and // executing a .NET stored procedure, which inserts a record into EMP // table and then verifies record count before and after COMMIT statement class TransactionSample { static void Main(string[] args) { OracleConnection Conn = null; OracleTransaction Txn = null; OracleCommand Cmd = null; try { Console.WriteLine( "Sample: Open DB connection in non auto-committed " + "mode," + "DML operation performed by .NET stored " + "procedure doesn't have an effect before COMMIT " + "is called." ); // Create and Open oracle connection Conn = new OracleConnection(); Conn.ConnectionString = "User Id=scott;Password=tiger;" + "Data Source=oracle;"; Conn.Open(); // Start transaction Txn = Conn.BeginTransaction( IsolationLevel.ReadCommitted ); // Create command object Cmd = new OracleCommand(); Cmd.Connection = Conn; Cmd.CommandType = CommandType.StoredProcedure; Cmd.CommandText = "InsertRecord"; // .NET Stored procedure // Parameter settings OracleParameter EmpNoPrm = Cmd.Parameters.Add( "empno", OracleDbType.Int32 ); EmpNoPrm.Direction = ParameterDirection.Input; EmpNoPrm.Value = 7950; OracleParameter EmpNamePrm = Cmd.Parameters.Add( "ename", OracleDbType.Varchar2, 10 ); EmpNamePrm.Direction = ParameterDirection.Input; EmpNamePrm.Value = "Bernstein"; // Execute .NET stored procedure Cmd.ExecuteNonQuery(); Console.WriteLine( "Number of record(s) before COMMIT {0}", RecordCount() ); Txn.Commit(); Console.WriteLine( "Number of record(s) after COMMIT {0}", RecordCount() ); } catch( OracleException OE ) { Console.WriteLine( OE.Message ); } finally { // Cleanup objects if( null != Txn ) Txn.Dispose(); if( null != Cmd ) Cmd.Dispose(); if( null != Conn && Conn.State == ConnectionState.Open ) Conn.Close(); } } static int RecordCount() { int EmpCount = 0; OracleConnection Conn = null; OracleCommand Cmd = null; try { Conn = new OracleConnection( "User Id=scott;Password=tiger;" + "Data Source=oracle;" ); Conn.Open(); Cmd = new OracleCommand( "SELECT COUNT(*) FROM EMP", Conn ); Object o = Cmd.ExecuteScalar(); EmpCount = Convert.ToInt32(o.ToString()); } catch( OracleException OE ) { Console.WriteLine( OE.Message ); } finally { if( null != Cmd ) Cmd.Dispose(); } return EmpCount; } }