この項では、Oracle Data Provider for .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;
}
}