Skip Headers

Oracle Data Provider for .NET Developer's Guide
Release 9.2.0.2

Part Number A96160-01
Go To Table Of Contents
Contents
Go To Index
Index

Go to previous page Go to next page

3
Features of Oracle Data Provider for .NET

This chapter describes Oracle Data Provider for .NET provider-specific features and how to use them to develop .NET applications.

This chapter contains these topics:

Connecting to the Oracle Database Server

This section describes OracleConnection provider-specific features, including:

Connection String Attributes

Table 3-1 lists the supported connection string attributes.

Table 3-1 Supported Connection String Attributes  
Connection String Attribute Default value Description

Connection Lifetime

0

Maximum life time (in seconds) of the connection

Connection Timeout

15

Maximum time (in seconds) to wait for a free connection from the pool

Data Source

empty string

Oracle Net Service Name that identifies the database to connect to

DBA Privilege

empty string

Administrative privileges: SYSDBA or SYSOPER

Decr Pool Size

1

Controls the number of connections that are closed when an excessive amount of established connections are unused

Enlist

true

Enables or disables Serviced Components to automatically enlist in distributed transactions

Incr Pool Size

5

Controls the number of connections that are established when all the connections in the pool are used

Max Pool Size

100

Maximum number of connections in a pool

Min Pool Size

1

Minimum number of connections in a pool

Password

empty string

Password for the user specified by User Id

Persist Security Info

false

Enables or disables the retrieval of password in the connection string

Pooling

true

Enables or disables connection pooling

Proxy User Id

empty string

User name of the proxy user

Proxy Password

empty string

Password of the proxy user

User Id

empty string

Oracle user name

The following example uses connection string attributes to connect to an Oracle database:

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;";
con.Open();
...

See Also:

"ConnectionString" for detailed information on connection attributes

Connection Pooling

ODP.NET connection pooling is enabled and disabled using the Pooling connection string attribute. By default, connection pooling is enabled. The following are ConnectionString attributes that control the behavior of the connection pooling service:

Connection Pooling Example

For example, the following code opens a connection using ConnectionString attributes related to connection pooling.

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;" +
         "Min Pool Size=10;Connection Lifetime=120;Connection Timeout=60;" +
         "Incr Pool Size=5; Decr Pool Size=2";
con.Open();
...

With connection pooling enabled, the Open and Close methods of the OracleConnection object implicitly use the connection pooling service. The connection pooling service is part of ODP.NET. In the code above, the Open call uses the connection pooling service, which is responsible for returning a connection to the application.

Connection pools are created by the connection pooling service with the ConnectionString as the signature to uniquely identify a pool. If a pool does not exist with a ConnectionString acting as a signature, the connection pooling service creates a new connection pool. If a pool already exists with the exact attribute values in the ConnectionString, a connection is returned to the application from the pool.

When a connection pool is created, the connection-pooling service initially creates the number of connections defined by the Min Pool Size attribute of the ConnectionString. This number of connections is always maintained by the connection pooling service for the connection pool.

At any given time, these connections can be available in the pool or used by the application. When a request for a connection comes to the connection pooling service, the connection pooling service goes to the right connection pool and returns an available connection from the pool. If there is no connection available, the connection pooling service creates and returns a new connection. The Incr Pool Size attribute of the ConnectionString defines the number of new connections to be created by the connection pooling service when more connections are needed in the connection pool.

When the application closes a connection, the connection pooling service determines whether the connection lifetime has exceeded the Connection Lifetime attribute; if so, the connection pooling service closes the connection; otherwise, the connection goes back to the connection pool. The connection pooling service only enforces the Connection Lifetime when a connection is going back to the connection pool.

The Max Pool Size attribute of the ConnectionString sets the maximum number of connections for a connection pool. If a new connection is requested, no connections are available, and Max Pool Size has been reached, then the connection pooling service waits for the time defined by Connection Timeout. If the Connection Timeout has been reached and there are still no connections available in the pool, the connection pooling service raises an exception indicating a new connection is not available.

The connection pooling service closes connections when they are not used; connections are closed every three minutes. The Decr Pool Size attribute of the ConnectionString provides connection pooling service for the maximum number of connections that can be closed in one run.

OS Authentication

The Oracle database server can use Windows user login credentials to authenticate database users. To open a connection using Windows user login credentials, the User Id ConnectionString attribute must be set to /. If Password is provided, it is ignored.

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=/;Data Source=oracle;";
con.Open();
...

See Also:

Oracle9i Security and Network Integration Guide for Windows for information on how to set up Oracle to authenticate database users using Windows user login credentials

Privileged Connections

Oracle allows database administrators to connect to an Oracle database with either SYSDBA or SYSOPER privileges. This is done through the DBA Privilege attribute of the ConnectionString.

The following example connects SYS/SYS as SYSDBA:

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=SYS;Password=SYS;" +
    "DBA Privilege=SYSDBA;Data Source=oracle;";
con.Open();
...

See Also:

"DBA Privilege" for further information on privileged connections in the database

Password Expiration

Oracle allows users' password to expire. ODP.NET lets applications handle the password expiration by providing a new method, OpenWithNewPassword, that opens the connection with a new password.

The following code snippet uses the OracleConnection OpenWithNewPassword method to connect with a new password of panther:

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;";
con.Open();
//  Here the con.Open() fails if the password has expired.
//  An application catches this and asks for the new password and call following 
//  API. The initial connection string must remain intact.
//  The following API gives panther as the new Password.

con.OpenWithNewPassword("panther");
...


Note:

OpenWithNewPassword should only be used when the user password has expired, not for changing the password.


See Also:

"OpenWithNewPassword" for further information password expiration in the Oracle database

Proxy Authentication

Oracle allows a middle-tier server to connect to proxy clients in a secure fashion.

In multi-tier environments, proxy authentication allows control of middle-tier application security by preserving client identities and privileges through all tiers, and auditing actions taken on behalf of clients. For example, this feature allows the identity of a user using a web application (also known as a proxy) to be passed through the application to the database server.

ODP.NET supports proxy authentication with or without a client password by providing the Proxy User Id and Proxy Password attributes of the ConnectionString property.

// C#
...
OracleConnection con = new OracleConnection();
// Connecting using proxy authentication
con.ConnectionString = "User Id=customer;Password=lion;" + 
     "Data Source=oracle;Proxy User Id=appserver;Proxy Password=eagle; ";
con.Open();
...

See Also:

Transparent Application Failover (TAF) Callback Support

Transparent Application Failover (TAF) is a feature in Oracle that provides high availability.

TAF enables an application connection to automatically reconnect to a database if the connection fails. Active transactions roll back, but the new database connection, made by way of a different node, is identical to the original. This is true regardless of how the connection fails.

With Transparent Application Failover, a client notices no loss of connection as long as there is one instance left serving the application. The database administrator controls which applications run on which instances and also creates a failover order for each application.

Due to the delay that a failover can incur, the application may wish to be notified by a TAF callback. ODP.NET supports TAF callback through the Failover event of the OracleConnection object. To receive TAF callbacks, an event handler function must be registered with the Failover event.

When a failover occurs, the Failover event is raised and the registered event handler is invoked several times during the course of reestablishing the connection to another Oracle instance.

The first call to the event handler occurs when the Oracle database server first detects an instance connection loss. This allows the application to act accordingly for the upcoming delay for the failover. If the failover is successful, the Failover event is raised again when the connection is reestablished and usable. At this time, the application can resynchronize the OracleGlobalization session setting and inform the application user that a failover has occurred.

If failover is unsuccessful, the Failover event is raised to inform the application that a failover did not take place. The application can determine whether or not the failover is successful by checking the OracleFailoverEventArgs that is passed to the event handler.

The following code snippet registers an event handler method called OnFailover:


// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;";
con.Open();
con.Failover += new OracleFailoverEventHandler(OnFailover);
...

The Failover event only invokes one event handler. If multiple Failover event handlers are registered with the Failover event, only the event handler registered last is invoked.

See Also:

ODP.NET Types Overview

ODP.NET types represent Oracle native types as a structure or as a class. ODP.NET type structures follow value semantics while ODP.NET type classes follow reference semantics. ODP.NET types provide a safer and efficient way of obtaining Oracle native data in a .NET application. For example, an OracleDecimal holds up to 38 precisions while a .NET Decimal holds only up to 28 precisions.

Table 3-2 lists all the Oracle native types supported by ODP.NET and their corresponding ODP.NET type. The third column lists the .NET Framework datatype that corresponds to the Value property of each ODP.NET Type.

Table 3-2 Oracle Native Types Supported by ODP.NET  
Oracle Native Type ODP.NET Type .NET Framework Datatypes

BFILE

OracleBFile class

System.Byte[]

BLOB

OracleBlob class

System.Byte[]

CHAR

OracleString structure

System.String

CLOB

OracleClob class

System.String

DATE

OracleDate structure

System.DateTime

INTERVAL DAY TO SECOND

OracleIntervalDS structure

System.TimeSpan

INTERVAL YEAR TO MONTH

OracleIntervalYM structure

System.Int64

LONG

OracleString structure

System.String

LONG RAW

OracleBinary structure

System.Byte[]

NCLOB

OracleClob class

System.String

NCHAR

OracleString structure

System.String

NUMBER

OracleDecimal structure

System.Decimal

NVARCHAR2

OracleString structure

System.String

RAW

OracleBinary structure

System.Byte[]

REF CURSOR

OracleRefCursor class

Not Applicable

TIMESTAMP

OracleTimeStamp structure

System.DateTime

TIMESTAMP WITH LOCAL TIME ZONE

OracleTimeStampLTZ structure

System.DateTime

TIMESTAMP WITH TIME ZONE

OracleTimeStampTZ structure

System.DateTime

VARCHAR2

OracleString structure

System.String

Obtaining Data From an OracleDataReader

The ExecuteReader method of the OracleCommand object returns an OracleDataReader object, which is a read-only, forward-only result set.

This section provides the following information about the OracleDataReader:

Typed OracleDataReader Accessors

The OracleDataReader provides two types of typed accessors:

.NET Type Accessors

Table 3-3 lists all the Oracle native database types that ODP.NET supports and the corresponding .NET Type that best represents the Oracle native type. The third column indicates the valid typed accessor that can be invoked for an Oracle native type to be obtained as a .NET type. If an invalid typed accessor is used for a column, an InvalidCastException is thrown. Oracle native datatypes depend on the version of the database; therefore, some datatypes are not available in earlier versions of Oracle.

See Also:

"OracleDataReader Class" for more information

Table 3-3 .NET Type Accessors  
Oracle Native Datatype .NET Type Typed Accessor

BFILE

System.Byte[ ]

GetBytes

BLOB

System.Byte[ ]

GetBytes

CHAR

System.String

GetString

GetChars

CLOB

System.String

GetString

GetChars

DATE

System.DateTime

GetDateTime

INTERVAL (DS)

System.Interval

GetTimeSpan

INTERVAL (YM)

System.Interval

GetTimeSpan

LONG

System.String

GetString

GetChars

LONG RAW

System.Byte[ ]

GetBytes

NCHAR

System.String

GetString

GetChars

NCLOB

System.String

GetString

GetChars

NUMBER

System.Decimal

GetDecimal

NVARCHAR2

System.String

GetString

GetChars

RAW

System.Byte[ ]

GetBytes

ROWID

System.String

GetString

GetChars

TIMESTAMP

System.TimeStamp

GetTimeStamp

TIMESTAMP WITH LOCAL TIME ZONE

System.TimeStamp

GetTimeStamp

TIMESTAMP WITH TIME ZONE

System.TimeStamp

GetTimeStamp

UROWID

System.String

GetString

GetChars

VARCHAR2

System.String

GetString

GetChars

ODP.NET Type Accessors

ODP.NET has introduced several new types that natively represent the datatypes in Oracle. There are several advantages of using types introduced by ODP.NET over .NET types.

See Also:

"ODP.NET Types Overview" for a list of all ODP.NET types

Table 3-4 lists the valid ODP.NET type accessors used to obtain ODP.NET Types for an Oracle native type.

Table 3-4 ODP.NET Type Accessors  
Oracle Native Database Type ODP.NET Type Typed Accessor

BFILE

OracleBFile

GetOracleBFile

BLOB

OracleBlob

OracleBlob

OracleBinary

GetOracleBlob

GetOracleBlobForUpdate

GetOracleBinary

CHAR

OracleString

GetOracleString

CLOB

OracleClob

OracleClob

OracleString

GetOracleClob

GetOracleClobForUpdate

GetOracleString

DATE

OracleDate

GetOracleDate

INTERVAL (DS)

OracleIntervalDS

GetOracleIntervalDS

INTERVAL (YM)

OracleIntervalYM

GetOracleIntervalYM

LONG

OracleString

GetOracleString

LONG RAW

OracleBinary

GetOracleBinary

NCHAR

OracleString

GetOracleString

NCLOB

OracleString

GetOracleString

NUMBER

OracleDecimal

GetOracleDecimal

NVARCHAR2

OracleString

GetOracleString

RAW

OracleBinary

GetOracleBinary

ROWID

OracleString

GetOracleString

TIMESTAMP

OracleTimeStamp

GetOracleTimeStamp

TIMESTAMP WITH LOCAL TIME ZONE

OracleTimeStampLTZ

GetOracleTimeStampLTZ

TIMESTAMP WITH TIME ZONE

OracleTimeStampTZ

GetOracleTimeStampTZ

UROWID

OracleString

GetOracleString

VARCHAR2

OracleString

GetOracleString

Obtaining LONG and LONG RAW Data

When an OracleDataReader is created containing LONG or LONG RAW types, OracleDataReader defers the fetch of the LONG or LONG RAW column data. The initial number of characters for LONG or bytes for LONG RAW fetched on the client side depends on the InitialLONGFetchSize property of the OracleCommand. By default, InitialLONGFetchSize is 0.

ODP.NET does not support CommandBehavior.SequentialAccess. Therefore, LONG and LONG RAW data can be fetched in a random fashion.

To obtain data beyond InitialLONGFetchSize bytes or characters, a primary key column must be provided in the list of selected columns. The requested data is fetched from the database when the appropriate typed accessor method (GetOracleString for LONG or GetOracleBinary for LONG RAW) is called on the OracleDataReader object.

In order to fetch the data in a non-defer mode or when the list of columns does not have a primary key column or a ROWID, set the size of the InitialLONGFetchSize property on the OracleCommand object to equal or greater than the amount of bytes or characters needs to be retrieved.

Controlling the Number of Rows Fetched in One Server Round-Trip

Application performance depends on the number of database round-trips to retrieve data. The less round-trips, the better the performance.

OracleCommand FetchSize Property

The OracleCommand FetchSize property defines the maximum number of rows that can be fetched in one server round-trip.

The FetchSize property takes the size of memory (in bytes) that is used by the OracleDataReader to fetch numbers rows from the database. If a query returns 100 rows and each row takes 1024 (1 K) bytes, then setting FetchSize to 102400 takes just one database round-trip to fetch the hundred rows. For the same query, if the FetchSize is set to 10240, it takes 10 database round-trips to retrieve 100 rows.

In order to set the FetchSize property to a proper value, the exact size of a row returned from the query must be used. This is provided by the RowSize property on the OracleCommand object. RowSize is a design time property, which is only populated after the execution of the query. Once the RowSize is available, it can be used to set the correct FetchSize on the command.

OracleDataReader FetchSize Property

Applications that do not know the exact size of a row at design time can use the FetchSize property of the OracleDataReader object. This FetchSize property should be set after invoking the ExecuteDataReader method of the OracleCommand object and before the first row is fetched using the Read method on the OracleDataReader object.

The RowSize property of the OracleCommand object is set by execution of the ExecuteDataReader. The RowSize property can then be used to set the value of the FetchSize property on the OracleDataReader object. This provides a dynamic way of setting the FetchSize property on the OracleDataReader based on the size of a row.

OracleCommand Object

The OracleCommand object represents SQL statements or stored procedures executed on the Oracle database server.

This section includes the following topics:

Transaction

The Oracle database server starts a transaction only in the context of a connection. Once a transaction starts on a connection, all the successive command execution on that connection run in the context of that transaction. ODP.NET reflects this by only starting a transaction on a OracleConnection object and not allowing the Transaction property on the OracleCommand object to be set. The Transaction property on the OracleCommand object is read-only and depends solely on the connection used for the command object.

Parameter Binding

ODP.NET allows applications to retrieve data as either a .NET Framework type or an ODP.NET type. If the application sets the OracleParameter's DbType property for an OUT parameter, the data is retrieved as .NET Framework type. That is, if the output parameter is bound as an DbType.String, the output data is returned as a .NET String.

On the other hand, if the application sets OracleParameter's OracleDbType property, the data is retrieved as a ODP.NET type. That is, if the parameter is bound as OracleDbType.Char, the output data is returned as OracleString type.

When the DbType of an OracleParameter is set, the OracleDbType of the OracleParameter changes accordingly, and vice versa.

Lastly, an application can simply bind the data and have ODP.NET infer both the DbType and OracleDbType from the .NET type of the parameter value.

ODP.NET populates InputOutput, Output, and ReturnValue parameters with the Oracle data, through the execution of the following OracleCommand methods:

An application should not bind a value for output parameters; it is the responsibility of ODP.NET to create the value object and populate the OracleParameter Value property with the object.

This section describes the following:

OracleDbType Enumeration Type

OracleDbType enumerated values are used to explicitly specify the OracleDbType of an OracleParameter.

Table 3-5 lists all the OracleDbType enumeration values with a description of each enumerated value.

Table 3-5 OracleDbType Enumeration Values  
Member Name Description

BFile

Oracle BFILE type

Blob

Oracle BLOB type

Byte

byte type

Char

Oracle CHAR type

Clob

Oracle CLOB type

Date

Oracle DATE type

Decimal

Oracle NUMBER type

Double

8-byte FLOAT type

Int16

2-byte INTEGER type

Int32

4-byte INTEGER type

Int64

8-byte INTEGER type

IntervalDS

Oracle INTERVAL DAY TO SECOND type

IntervalYM

Oracle INTERVAL YEAR TO MONTH type

Long

Oracle LONG type

LongRaw

Oracle LONG RAW type

NChar

Oracle NCHAR type

NClob

Oracle NCLOB type

NVarchar2

Oracle NVARCHAR2 type

Raw

Oracle RAW type

RefCursor

Oracle REF CURSOR type

Single

4-byte FLOAT type

TimeStamp

Oracle TIMESTAMP type

TimeStampLTZ

Oracle TIMESTAMP WITH LOCAL TIME ZONE type

TimeStampTZ

Oracle TIMESTAMP WITH TIME ZONE type

Varchar2

Oracle VARCHAR2 type

Inference of DbType, OracleDbType, and .NET Types

This section explains the inference from the System.Data.DbType, OracleDbType, and Value properties in the OracleParameter class.

In the OracleParameter class, DbType, OracleDbType, and Value properties are linked. Specifying the value of any of these properties infers the value of one or more of the other properties.

Inference of DbType from OracleDbType

In the OracleParameter class, specifying the value of OracleDbType infers the value of DbType as shown in Table 3-6.

Table 3-6 Inference of System.Data.DbType from OracleDbType  
OracleDbType System.Data.DbType

BFile

Object

Blob

Object

Byte

Byte

Char

StringFixedLength

Clob

Object

Date

Date

Decimal

Decimal

Double

Double

Int16

Int16

Int32

Int32

Int64

Int64

IntervalDS

TimeSpan

IntervalYM

Int64

Long

String

LongRaw

Binary

NChar

StringFixedLength

NClob

Object

NVarchar2

String

Raw

Binary

RefCursor

Object

Single

Single

TimeStamp

DateTime

TimeStampLTZ

DateTime

TimeStampTZ

DateTime

Varchar2

String

Inference of OracleDbType from DbType

In the OracleParameter class, specifying the value of DbType infers the value of OracleDbType as shown in Table 3-7.

Table 3-7 Inference of OracleDbType from DbType  
System.Data.DbType OracleDbType

AnsiString

Varchar2

AnsiStringFixedLength

Char

Binary

Raw

Boolean

Not Supported

Byte

Byte

Currency

Not Supported

Date

Date

DateTime

TimeStamp

Decimal

Decimal

Double

Double

Guid

Not Supported

Int16

Int16

Int32

Int32

Int64

Int64

Object

Not Supported

Sbyte

Not Supported

Single

Single

String

Varchar2

StringFixedLength

Char

Time

TimeStamp

UInt16

Not Supported

UInt32

Not Supported

Uint64

Not Supported

VarNumeric

Not Supported

Inference of DbType and OracleDbType from Value

In the OracleParameter class, Value is an object type which can be of any .NET Framework datatype or ODP.NET type. If the OracleDbType and DbType in the OracleParameter object are not specified, OracleDbType is inferred from the type of the Value property.

Table 3-8 shows the inference of DbType and OracleDbType from Value when the type of Value is one of the .NET Framework datatypes.

Table 3-8 Inference of DbType and OracleDbType from Value (.NET Datatypes)  
Value (.NET Datatypes) System.Data.DbType OracleDbType

Byte

Byte

Byte

Byte[]

Binary

Raw

Char / Char []

String

Varchar2

DateTime

DateTime

TimeStamp

Decimal

Decimal

Decimal

Double

Double

Double

Float

Single

Single

Int16

Int16

Int16

Int32

Int32

Int32

Int64

Int64

Int64

Single

Single

Single

String

String

Varchar2

TimeSpan

TimeSpan

IntervalDS


Note:

Using other .NET Framework datatypes as values for OracleParameter without specifying either the DbType or the OracleDbType raises an exception because inferring DbType and OracleDbType from other .NET Framework datatypes is not supported.


Table 3-9 shows the inference of DbType and OracleDbType from Value when type of Value is one of Oracle.DataAccess.Client.

Table 3-9 Inference of DbType and OracleDbType from Value (ODP.NET Types)  
Value (Oracle.DataAccess.Client) System.Data.DbType OracleDbType

OracleBFile

Object

BFile

OracleBinary

Binary

Raw

OracleBlob

Object

Blob

OracleClob

Object

Clob

OracleDate

Date

Date

OracleDecimal

Decimal

Decimal

OracleIntervalDS

TimeSpan

IntervalDS

OracleIntervalYM

Int64

IntervalYM

OracleRefCursor

Object

RefCursor

OracleString

String

Varchar2

OracleTimeStamp

DateTime

TimeStamp

OracleTimeStampLTZ

DateTime

TimeStampLTZ

OracleTimeStampTZ

DateTime

TimeStampTZ

Array Binding

The array bind feature enables applications to bind arrays of a type using the OracleParameter class. Using the array bind feature, an application can insert multiple rows into a table in a single database round-trip.

The following code example inserts three rows into the Dept table with a single database round-trip. The OracleCommand ArrayBindCount property defines the number of elements of the array to use when executing the statement.

// C# 
... 
// Create an array of values that need to be inserted 
int[] myArrayDeptNo = new int[3]{10, 20, 30}; 

// Set the command text on an OracleCommand object 
cmd.CommandText = "insert into dept(deptno) values (:deptno)"; 
// Set the ArrayBindCount to indicate the number of values 
cmd.ArrayBindCount = 3; 

// Create a parameter for the array operations 
OracleParameter prm = new OracleParameter("deptno", OracleDbType.Int32); 
prm.Direction = ParameterDirection.Input; 
prm.Value     = myArrayDeptNo; 

// Add the parameter to the parameter collection 
cmd.Parameters.Add(prm); 

// Execute the command 
cmd.ExecuteNonQuery(); 

See Also:

"Value" for more information

OracleParameter Array Bind Properties

The OracleParameter object provides two properties for granular control when using the array bind feature:

OracleParameterStatus Enumeration Types

Table 3-10 provides different value for OracleParameterStatus enumeration.

Table 3-10 OracleParameterStatus Members  
Member Names Description

Success

For input parameters, it indicates that the input value has been assigned to the column

For output parameters, it indicates that the provider assigned an intact value to the parameter

NullFetched

Indicates that a NULL value has been fetched from a column or an OUT parameter

NullInsert

Indicates that a NULL value is to be inserted into a column

Truncation

Indicates that truncation has occurred when fetching the data from the column

PL/SQL REF CURSOR and OracleRefCursor

The REF CURSOR is a datatype in the Oracle PL/SQL language. It represents a cursor or a result set in the Oracle database server. The OracleRefCursor is a corresponding ODP.NET type for the REF CURSOR type.

This section discusses the following aspects of using REF CURSOR and OracleRefCursor objects:

Obtaining an OracleRefCursor

There are no constructors for OracleRefCursor objects. They can only be acquired as parameter values from PL/SQL stored procedures, stored functions, or anonymous blocks.

An OracleRefCursor is a connected object. The connection used to execute the command returning a OracleRefCursor object is required for its lifetime. Once the connection associated with an OracleRefCursor is closed, the OracleRefCursor cannot be used.

Obtaining a REF CURSOR

A REF CURSOR can be obtained as an OracleDataReader, DataSet, or OracleRefCursor. If the REF CURSOR is obtained as an OracleRefCursor object, it can be used to create an OracleDataReader or populate a DataSet from it. When accessing a REF CURSOR, always bind as a OracleDbType.RefCursor.

Populating an OracleDataReader from a REF CURSOR

An Oracle REF CURSOR can be obtained as an OracleDataReader by calling the OracleCommand ExecuteReader method. The output parameter with the OracleDbType property set is bound to OracleDbType.RefCursor. None of the output parameters of type OracleDbType.RefCursor are populated after the ExecuteReader is invoked.

If there are multiple output REF CURSOR parameters, use the OracleDataReader NextResult method to access the next REF CURSOR. The OracleDataReader NextResult method provides sequential access to the REF CURSORs; only one REF CURSOR can be accessed at a given time.

The order in which OracleDataReader objects are created for the corresponding REF CURSOR depends on the order in which the parameters are bound. If a PL/SQL stored function returns a REF CURSOR, then it becomes the first OracleDataReader and all the output REF CURSOR objects follow the order in which the parameters are bound.

Populating the DataSet From a REF CURSOR

For the Fill method to populate the DataSet properly, the SelectCommand of the OracleDataAdapter must be bound with an output parameter of type OracleDbType.RefCursor. If the Fill method is successful, the DataSet is populated with a DataTable that represents a REF CURSOR.

If the command execution returns multiple REF CURSORs, the DataSet is populated with multiple DataTables.

Populating an OracleRefCursor From a REF CURSOR

When ExecuteNonQuery is invoked on a command that returns one or more REF CURSORs, each of the OracleCommand parameters that are bound as OracleDbType.RefCursor gets a reference to an OracleRefCursor object.

To create an OracleDataReader from an OracleRefCursor object, invoke GetDataReader from an OracleRefCursor object. Subsequent calls to GetDataReader return the reference to the same OracleDataReader.

To populate a DataSet with an OracleRefCursor object, the application can invoke an OracleDataAdapter Fill method that takes an OracleRefCursor object.

When multiple REF CURSORs are returned from a command execution as OracleRefCursor objects, the application can choose to create an OracleDataReader or populate a DataSet with a particular OracleRefCursor object. All the OracleDataReaders or DataSet created from the OracleRefCursor are active at the same time and can be accessed in any order.

Updating a DataSet Obtained From a REF CURSOR

REF CURSORs are not updatable. However, data that is retrieved into a DataSet can be updated. Therefore, the OracleDataAdapter requires a custom SQL statement to flush any REF CURSOR data updates to the database.

The OracleCommandBuilder cannot be used to generate SQL for REF CURSOR updates.

Behavior of ExecuteScalar Method for REF CURSOR

ExecuteScalar returns the return value of a stored function or the first bind parameter of a stored procedure or an anonymous PL/SQL block. Therefore, if the REF CURSOR is not the return value of a stored function or the first bind parameter of a stored procedure or an anonymous PL/SQL block, the REF CURSOR is ignored by ExecuteScalar.

However, if the REF CURSOR is a return value of a stored function or the first bind parameter of a stored procedure or an anonymous PL/SQL block, the value of the first column of the first row in the REF CURSOR is returned.

See Also:

Oracle9i Application Developer's Guide - Large Objects (LOBs) for more information

LOB Support

ODP.NET provides an easy and optimal way to access and manipulate large datatypes. Oracle supports large character and large binary datatypes.

Large Character Datatypes
Large Binary Datatypes

ODP.NET provides three objects for LOBs for manipulating LOB data: OracleBFile, OracleBlob, and OracleClob.

Table 3-11 below shows the proper ODP.NET class to use for a particular Oracle LOB type.

Table 3-11 ODP.NET LOB Objects
Oracle LOB Type ODP.NET LOB object

BFILE

OracleBFile object

BLOB

OracleBlob object

CLOB

OracleClob object

NCLOB

OracleClob object

The ODP.NET LOB objects can be obtained by calling the proper typed accessor on the OracleDataReader or as an output parameter on a command execution with the proper bind type.

All ODP.NET LOB objects inherit from the .NET Stream class to provide generic Stream operations. The LOB data (except for BFILEs) can be updated using the ODP.NET LOB objects by using methods such as Write. Data is not cached in the LOB objects when read and write operations are carried out. Therefore, each Read or Write request incurs a server round-trip. The OracleClob overloads the Read method, providing two ways to read data from a CLOB. The Read method, which takes a byte[] as the buffer, populates it with CLOB data as Unicode byte array. Conversely, the Read method, which takes a char[] as the buffer, populates it with Unicode characters.

Extensions can also be found on the OracleBFile object. An OracleBFile object must be explicitly opened using the OpenFile method before any data can be read from it. To close a previously opened BFILE, use the CloseFile method.

Every ODP.NET LOB object is a connected object and requires a connection during its lifetime. If the connection associated with a LOB object is closed, then the LOB object is not usable and should be disposed.

If an ODP.NET LOB object is obtained from an OracleDataReader through a typed accessor, then its Connection property is set with a reference to the same OracleConnection object used by the OracleDataReader. If a LOB object is obtained as an output parameter, then its Connection property is set with a reference to the same OracleConnection property used by the OracleCommand. If a LOB object is obtained by invoking an ODP.NET LOB object constructor to create a temporary LOB, the Connection property is set with a reference to the OracleConnection object provided in the constructor.

The ODP.NET LOB object Connection property is read-only and cannot be changed during its lifetime. In addition, the ODP.NET LOB types object can only be used within the context of the same OracleConnection referenced by the ODP.NET LOB object. For example, the ODP.NET LOB object's Connection must reference the same connection as the OracleCommand if the ODP.NET LOB object is a parameter of the OracleCommand. If that is not the case, ODP.NET raises an exception when the command is executed.

See Also:

Oracle9i Application Developer's Guide - Large Objects (LOBs) for complete information about Oracle9i LOBs and how to use them

Updating LOBs Using a DataSet

BFILE and BLOB data are stored in the DataSet as byte arrays while CLOB and NCLOB data are stored as strings. Similarly to other types, an OracleDataAdapter object can be used to fill and update LOB data changes along with the use of the OracleCommandBuilder for auto-generating SQL.

Note that an Oracle LOB column can store up to 4 GB of data. When the LOB data is fetched into the DataSet, the actual amount of LOB data the DataSet can hold for a LOB column is limited to the maximum size of a .NET string type, which is 2 GB. Therefore, when fetching LOB data that is greater than 2 GB, ODP.NET LOB objects must be used to avoid any data loss.

Updating LOBs Using OracleCommand and OracleParameter

To update LOB columns, LOB data can be bound as a parameter for SQL statements, anonymous PL/SQL blocks, or stored procedures. The parameter value can be set as a NET Framework type, ODP.NET type, or as an ODP.NET LOB object type. For example, when inserting a .NET string data into a LOB column in a Oracle9i database, that parameter can be bound as OracleDbType.Varchar2. For a parameter whose value is set to an OracleClob object, the parameter should be bound as OracleDbType.Clob.

Updating LOBs Using ODP.NET LOB Objects

Oracle BFILEs are not updatable and hence OracleBFile objects do not allow updates to BFILE columns.

Two requirements must be met to update LOB data using ODP.NET LOB objects.

  1. A transaction must be started before a LOB column is selected.

    The transaction must be started using the BeginTransaction method on the OracleCommand before the command execution so that the lock can be released when OracleTransaction Commit or Rollback is invoked.

  2. The row in which the LOB column resides must be locked; on a row by row basis or as part of an entire result set.

    1. Locking the entire result

      Add the FOR UPDATE clause to the end of the SELECT statement. After execution of the command, the entire result set is locked.

    2. Locking the row - There are two options:

      • Invoke one of OracleDataReader's typed accessors (GetOracleClobForUpdate or GetOracleBlobForUpdate) on the OracleDataReader to obtain an ODP.NET LOB object while also locking the current row.

        This approach requires a primary key or a ROWID in the result set because the OracleDataReader must uniquely identify the row to re-select it for locking.

      • Execute a SELECT statement that returns a LOB in the RETURNING clause.

Temporary LOBs

Temporary LOBs can be instantiated for BLOBs, CLOBs, and NCLOBs. To instantiate an ODP.NET LOB object that represents a temporary LOB, the OracleClob or the OracleBlob constructor can be used.

Temporary ODP.NET LOB objects can be used for the following purposes:

Globalization Support

ODP.NET globalization support enables applications to manipulate culture-sensitive data appropriately. This feature ensures proper string format, date, time, monetary, numeric, sort order, and calendar conventions depending on the Oracle globalization settings.

See Also:

"OracleGlobalization Class"

This section includes the following:

Globalization Settings

An OracleGlobalization object can be used to represent the following:

Client Globalization Settings

Client globalization settings are derived from the Oracle globalization setting (NLS_LANG) in the Windows registry of the local computer. The client globalization parameter settings are read-only and remain constant throughout the lifetime of the application. The client globalization settings can be obtained by calling the OracleGlobalization.GetClientInfo() static method.

The following example retrieves the client globalization setting:

// C#
...
// GetClientInfo() is a static method on OracleGlobalization class
OracleGlobalization ClientGlob = OracleGlobalization.GetClientInfo();

The properties of the OracleGlobalization object provide the Oracle globalization value settings.

Session Globalization Settings

Session globalization parameters are initially identical to client globalization settings. Unlike client settings, session globalization settings can be updated. However, they can only be obtained after establishing a connection against the database. The session globalization settings can be obtained by calling GetSessionInfo() on the OracleConnection. Invoking this method returns an instance of an OracleGlobalization object whose properties represent the globalization settings of the session.

When the OracleConnection object establishes a connection, it implicitly opens a session whose globalization parameters are initialized with those values specified by the client computer's Oracle globalization (or National Language Setting (NLS)) registry settings. The session settings are updatable and can change during its lifetime.

The following example changes the date format setting on the session:

// C#
...
OracleConnection con = new OracleConnection("User Id=scott;Password=tiger;");
con.Open();
OracleGlobalization SessionGlob = con.GetSessionInfo();

// SetSessionInfo updates the Session with the new value
SessionGlob.DateFormat = "YYYY/MM/DD"; 
con.SetSessionInfo(SessionGlob);       
...

Thread-Based Globalization Settings

Thread-based globalization parameter settings are specific to each thread. Initially, these settings are identical to the client globalization parameters, but they can be changed as specified by the application. When ODP.NET Types are converted to and from strings, the thread-based globalization parameters are used, if applicable.

Thread-based globalization parameter settings are obtained by invoking the GetThreadInfo static method of the OracleGlobalization object. The SetThreadInfo static method of the OracleGlobalization object can be called to set the thread's globalization settings.

ODP.NET classes and structures rely solely on the OracleGlobalization settings when manipulating culture-sensitive data. They do not use .NET thread culture information. If the application uses only .NET types, OracleGlobalization settings have no effect. However, when conversions are made between ODP.NET types and .NET types, OracleGlobalization settings are used where applicable.


Note:

Changes to System.Threading.Thread. CurrentThread.CurrentCulture do not impact the settings of the OracleGlobalization settings of the thread or the session and vice versa.


The following code snippet shows how the thread's globalization settings are used by the ODP.NET Types:

...
OracleGlobalization ThreadGlob = OracleGlobalization.GetThreadInfo();
// set and validate the format
ThreadGlob.DateFormat = "YYYY-MM-DD";

// set the thread with the new format
OracleGlobalization.SetThreadInfo(ThreadGlob); 

// create a new instance of OracleDate
OracleDate date = new OracleDate("2002-01-01"); 
...

The OracleGlobalization object validates property changes made to it. If an invalid value is used to set a property, an exception is thrown. Note that changes made to the Territory and Language properties change other properties of the OracleGlobalization object implicitly.

See Also:

Oracle9i Database Globalization Support Guide for more information on the properties affected by Territory and Language Globalization settings

Globalization-Sensitive Operations

This section lists ODP.NET types and operations that are dependent on or sensitive to globalization settings.

Operations Dependent on Client Computer's Globalization Settings

The OracleString structure depends on the client computer's OracleGlobalization settings. The local computer's client character set is used when it converts a Unicode string to a byte[] in the GetNonUnicode method and when it converts a byte[] of ANSI characters to Unicode in the OracleString constructor which accepts a byte[].

The local computer's client character set is also used by the OracleCommand when parameters are bound as DbType.AnsiString or DbType.AnsiStringFixedLength.

Input Parameters

As input parameters, the parameter value must be in the character set specified by the OracleGlobalization object's ClientCharacterSet property if it is bound as either DbType.AnsiString or DbType.AnsiStringFixedLength.

Output parameters

As output parameters, those parameter values that are bound as DbType.AnsiString or DbType.AnsiStringFixedLength are populated with ANSI string data in the character set specified by the OracleGlobalization object's ClientCharacterSet property.

Note that the ClientCharacterSet property is read-only and its value is the same regardless of whether the OracleGlobalization object represents the settings of the session, thread, or client.

Operations Dependent on Thread Globalization Settings

The thread globalization settings are used by ODP.NET types whenever they are converted to and from .NET string types, where applicable. In most cases, the ToString method, the Parse static method, constructors that accept .NET string data, and conversion operators to and from .NET strings use specific thread globalization settings depending on the ODP.NET type used.

For example, the OracleDate type uses the DateFormat property of the thread globalization settings when the ToString method is invoked on it. This returns a DATE as a string in the format specified by the thread's settings.

For more details, read the remarks in Chapter 5 for the ODP.NET type methods that convert between ODP.NET types and .NET string types, to identify which thread globalization settings are used for that particular method.

See Also:

Chapter 5, "Oracle.DataAccess.Types Namespace (ODP.NET Types)"

Operations Sensitive to Session Globalization Parameters

Session globalization settings affect any data that is retrieved from or sent to the server as a string.

For example, if a DATE column is selected with the TO_CHAR() function applied on it, the DATE column data will be a string in the date format specified by the DateFormat of the session globalization settings. Transmitting data in the other direction, the string data that is to be inserted into the DATE column, must be in the format specified by the DateFormat property of the session globalization settings.

The session globalization settings also affect data that is retrieved into the DataSet as a string using Safe Type Mapping. If the type is format-sensitive, the strings are always in the format specified by the session globalization settings.

For example, VARCHAR2 and CHAR data are not affected by session settings since no format is applicable for these types. However, the DateFormat and NumericCharacters properties can impact the string representation of DATE and NUMBER types, respectively, when they are retrieved as strings from the database through safe type mapping.

See Also:

"OracleDataAdapter Safe Type Mapping"

OracleDataAdapter Safe Type Mapping

The ODP.NET OracleDataAdapter provides the Safe Type Mapping feature because the following Oracle datatypes can potentially lose data when converted to their closely related .NET type:

When populating Oracle data containing any of the types defined above, into a .NET DataSet, there is a possibility of data loss. The OracleDataAdapter Safe Type Mapping feature prevents data loss. By setting the SafeMapping property appropriately, these types can be safely represented in the DataSet, as either of the following:

Potential Data Loss

The following sections provide more detail about the types and circumstances where data can be lost.

Oracle NUMBER Type to .NET Decimal Type

The Oracle datatype NUMBER can hold up to 38 precisions whereas .NET Decimal type can hold up to 28 precisions. If a NUMBER datatype that has more than 28 precisions is retrieved into .NET decimal type, it loses precision.

Table 3-12 lists the maximums and minimums for Oracle NUMBER and .NET Decimal.

Table 3-12 Oracle NUMBER to .NET Decimal Comparisons  
Oracle NUMBER .NET Decimal

Maximum

9.9999999999999999999999999999999999999 e125

79,228,162,514,264,337,593,543,950,335

Minimum

-9.9999999999999999999999999999999999999 e125

-79,228,162,514,264,337,593,543,950,335

Oracle Date Type to .NET DateTime Type

The Oracle datatype DATE can represent dates in BC whereas .NET DateTime cannot. If a DATE that goes to BC get retrieved into .NET DateTime type, it loses data.

Table 3-13 lists the maximums and minimums for Oracle Date and .NET DateTime.

Table 3-13 Oracle Date to .NET DateTime Comparisons  
Oracle Date .NET DateTime

Maximum

Dec 31, 9999 AD

Dec 31, 9999 AD 23:59:59.9999999

Minimum

Jan 1, 4712 BC

Jan 1, 0001 AD 00:00:00.0000000

Oracle TimeStamp Type to .NET DateTime Type

Similarly to DATE, Oracle datatype TimeStamp can represent a date in BC whereas .NET DateTime type cannot. If a TimeStamp that goes to BC is retrieved into .NET DateTime type, it loses data. Oracle TimeStamp type can represent values in units of e-9, whereas the .NET DateTime type can only represent values in units of e-7. The Oracle TimeStamp with time zone datatype can store time zone information whereas .NET DateTime cannot.

Table 3-14 lists the maximums and minimums for Oracle TimeStamp and .NET DateTime.

Table 3-14 Oracle TimeStamp to .NET DateTime Comparisons  
Oracle TimeStamp .NET DateTime

Maximum

Dec 31, 9999 AD 23:59:59.999999999

Dec 31, 9999 AD 23:59:59.9999999

Minimum

Jan 1, 4712 BC 00:00:00.000000000

Jan 1, 0001 AD 00:00:00.0000000

Oracle INTERVAL DAY TO SECOND to .NET TimeSpan

Similarly to DATE, the Oracle datatype INTERVAL DAY TO SECOND can represent dates in BC, whereas the .NET TimeSpan type cannot. If an INTERVAL DAY TO SECOND that goes to BC is retrieved into .NET TimeSpan type, it loses the data. The Oracle INTERVAL DAY TO SECOND type can represent values in units of e-9 whereas .NET TimeSpan type can only represent values in units of e-7.

Table 3-15 lists the maximums and minimums for Oracle INTERVAL DAY TO SECOND and .NET DateTime.

Table 3-15 Oracle INTERVAL DAY TO SECOND to .NET TimeSpan Comparisons  
Oracle INTERVAL DAY TO SECOND .NET TmeSpan

Maximum

+999999999 23:59:59.999999999

+10675199 02:48:05.4775807

Minimum

-999999999 23:59:59.999999999

-10675199 02:48:05.4775808

SafeMapping Property

By default, Safe Type Mapping is disabled.

Using Safe Type Mapping

To use the Safe Type Mapping functionality, the OracleDataAdapter.SafeMapping property must be set with a hashtable of key-value pairs. The key-value pairs must map database table column names (of type string) to a .NET type (of type Type). ODP.NET supports safe type mapping to byte[] and String types. Any other type mapping causes an exception.

In situations where the column names are not known at design time, an asterisk ("*") can be used to map all occurrences of database types to a safe .NET type where it is needed. If both the valid column name and the asterisk are present, the column name is used.


Note:

  • Database table column names are case sensitive.

  • Column names in the hashtable that correspond to invalid column names are ignored.


Mapping to a .NET String

The safe type mapping as a string is more readable without further conversion. Converting certain Oracle datatypes to a string requires extra conversion, which can be slower than converting it to a byte[]. Conversion of .NET strings back to ODP.NET types relies on the formatting information of the session.

OracleDataAdapter Requery Property

The OracleDataAdapter Requery property controls whether queries are reexecuted for OracleDataAdapter Fill calls after the initial Fill call.

The OracleDataAdapter Fill method allows appending or refreshing data in the DataSet. When appending the DataSet using the same query with subsequent Fill calls, it may be desired not to reexecute the query.

When the Requery property is set to true, each subsequent Fill call reexecutes the query and fills the DataSet. It is an expensive operation and if the reexecution is not required, set Requery to false. If any of the SelectCommand properties or associated parameters needs to be changed, Requery must be true.

When the Requery property is set to false, the DataSet has the entire data as a snapshot at a particular time. The query is executed only for the first Fill call, subsequent Fill calls fetch the data from a cursor opened with the first execution of the query. This feature is only supported for forward-only fetches. Fill calls that try to fetch rows before the last fetched row raise an exception. The connection used for the first Fill call must be available for subsequent Fill calls.

When filling a DataSet with a OracleRefCursor, the Requery property can be used in a similar manner. When the Requery property is set to false, both the connection used for the first Fill and the OracleRefCursor must be available for the subsequent Fill calls.

See Also:

Debug Tracing

ODP.NET provides debug tracing support, which allows logging of all the ODP.NET activities into a trace file. Different levels of tracing are available.

The provider can record the following information:

Registry Settings for Tracing Calls

The following registry settings should be configured under

HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ODP.NET

TraceFileName

The valid values for TraceFileName are: any valid path and filename

TraceFileName specifies the filename that is to be used for logging trace information. If TraceOption is set to 0, the name is used as is. However, if TraceOption is 1, the Thread ID is appended to the filename provided.

See Also:

"TraceOption"

TraceLevel

The valid values for TraceLevel are:

TraceLevel specifies the level of tracing in ODP.NET. Because tracing all the entry and exit calls for all the objects can be excessive, TraceLevel is provided to limit tracing to certain areas of the provider.

To obtain tracing on multiple objects, simply add the valid values. For example, if TraceLevel is set to 3, trace information is logged for Entry, Exit, and SQL and Distributed Transactions.

TraceOption

The valid values for TraceOption are:

TraceOption specifies whether to log trace information in single or multiple files for each Thread ID. If a single trace file is specified, the filename specified in TraceFileName is used. If the multiple trace files option is requested, a Thread ID is appended to the filename provided to create a trace file for each thread.


Go to previous page Go to next page
Oracle
Copyright © 2002 Oracle Corporation.

All Rights Reserved.
Go To Table Of Contents
Contents
Go To Index
Index