Skip Headers

Oracle® Data Provider for .NET Developer's Guide
10g Release 1 (10.1)

Part Number B10117-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Feedback

Go to previous page
Previous
Go to next page
Next
View PDF

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 Database.


See Also:

"OracleDataAdapter Class " for more information

Table 3-3 .NET Type Accessors

Oracle Native Datatype .NET Type Typed Accessor
BFILE System.Byte[] GetBytes
BINARY_DOUBLE System.Double GetDouble
BINARY_FLOAT System.Single GetFloat
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

XMLType System.String

System.Xml.XmlReader

GetString

GetXmlReader


ODP.NET Type Accessors

ODP.NET exposes provider-specific types that natively represent the datatypes in the database. In some cases, these ODP.NET types provide better performance and functionality that is not available to the corresponding .NET types. The ODP.NET types can be obtained from the OracleDataReader by calling their respective typed accessor.


See Also:

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

Table 3-4 lists the valid type accessors that ODP.NET uses 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
XMLType OracleString GetOracleString

OracleXmlType GetOracleXmlType

Obtaining LONG and LONG RAW Data

When an OracleDataReader is created containing a LONG or LONG RAW column type, OracleDataReader determines whether this column data needs to be fetched immediately or not, by checking the value of the InitialLONGFetchSize property of the OracleCommand that created the OracleDataReader.

By default, InitialLONGFetchSize is set to 0. If the InitialLONGFetchSize property value of the OracleCommand is left as 0, the entire LONG or LONG RAW data retrieval is deferred until that data is explicitly requested by the application. If the InitialLONGFetchSize property is set to a nonzero value, the LONG or LONG RAW data is immediately fetched up to the number of characters or bytes that the InitialLONGFetchSize property specifies.

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, one of the following must be in the select list:

  • primary key

  • ROWID

  • unique columns - (defined as a set of columns on which a unique constraint has been defined or a unique index has been created, where at least one of the columns in the set has a NOT NULL constraint defined on it)

The requested data is fetched from the database when the appropriate typed accessor method (GetOracleString or GetString for LONG or GetOracleBinary or GetBytes for LONG RAW) is called on the OracleDataReader object.

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

Obtaining LOB Data

When an OracleDataReader is created containing LOB column types, OracleDataReader determines whether the LOB column data needs to be fetched immediately or not by checking the value of the InitialLONGFetchSize property of the OracleCommand that created the OracleDataReader. By default, InitialLOBFetchSize is set to 0. If the InitialLOBFetchSize property value of the OracleCommand is left as 0, the entire LOB data retrieval is deferred until that data is explicitly requested by the application. If the InitialLOBFetchSize property is set to a nonzero value, the LOB data is immediately fetched up to the number of characters or bytes that the InitialLOBFetchSize property specifies.

By default, when InitialLOBFetchSize property is 0, GetOracleBlob() and GetOracleClob() can be invoked on the OracleDataReader to obtain OracleBlob and OracleClob objects. However, if the InitialLOBFetchSize is set to a nonzero value, GetOracleBlob() and GetOracleClob() methods are disabled. In this scenario, the BLOB and CLOB data needs to be fetched by using GetBytes() and GetChars(), respectively.

Methods Supported or Not Supported for InitialLOBFetchSize

Table 3-5 and Table 3-6 list supported and not supported methods for the CLOB and BLOB datatypes when the OracleCommand InitialLOBFetchSize property is set to a nonzero value.

Table 3-5 OracleDataReader CLOB Methods

Supported Not Supported
GetChars GetOracleClob
GetString GetOracleClobForUpdate
GetValue GetOracleValue
GetValues GetOracleValues
GetOracleString

Table 3-6 OracleDataReader BLOB Methods

Supported Not Supported
GetBytes GetOracleBlob
GetValue GetOracleBlobForUpdate
GetValues GetOracleValue
GetOracleBinary GetOracleValues

LOB Data Fetching Considerations

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

To obtain data beyond InitialLOBFetchSize bytes or characters, one of the following must be in the select list:

  • primary key

  • ROWID

  • unique columns - (defined as a set of columns on which a unique constraint has been defined or a unique index has been created, where at least one of the columns in the set has a NOT NULL constraint defined on it)

The requested data is fetched from the database when the appropriate typed accessor method is called on the OracleDataReader object. Note that the primary key column is not required if InitialLOBFetchSize is set to 0.

In order to fetch the data in a non-defer mode or when the columns in the select list do not have a primary key column, a ROWID, or unique columns, set the size of the InitialLOBFetchSize property on the OracleCommand object to an amount equal to or greater than the bytes or characters that need to be retrieved.

Performance

Setting InitialLOBFetchSize to a nonzero value can improve performance in certain cases. Using InitialLOBFetchSize can provide better performance than retrieving the underlying LOB data using OracleBlob or OracleClob objects. This is true if an application does not need to obtain OracleBlob and OracleClob objects from the OracleDataReader and the size the LOB column data is not very large. InitialLOBFetchSize is particularly useful in cases where the size of the LOB column data returned by query is approximately the same for all the rows.

It is generally recommended that InitialLOBFetchSize be set to a value larger than the size of the LOB data for more than 80% of the rows returned by the query. For example, if the size of the LOB data is less than 1 KB in 80% of the rows and more than 1 MB for 20% of the rows, set InitialLOBFetchSize to 1 KB.

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

Application performance depends on the number of rows the application needs to fetch and the number of database round-trips that are needed to retrieve them.

Use of FetchSize

The FetchSize property represents the total memory size in bytes that ODP.NET allocates to cache the data fetched from a server round-trip.

The FetchSize property can be set either on the OracleCommand or the OracleDataReader depending on the situation. Additionally, the FetchSize property of the OracleCommand is inherited by the OracleDataReader and can be modified.

If the FetchSize property is set on the OracleCommand, then the newly created OracleDataReader inherits the FetchSize property of the OracleCommand. This inherited FetchSize can be left as is or modified to override the inherited value. The FetchSize property of the OracleDataReader object can be changed before the first Read method invocation, which allocates memory specified by the FetchSize. All subsequent fetches from the database use the same cache allocated for that OracleDataReader. Therefore, changing the FetchSize after the first Read method invocation has no effect.

Fine-Tuning FetchSize

By fine-tuning the FetchSize property, applications can control memory usage and the number of rows fetched in one server round-trip for better performance. For example, if a query returns 100 rows and each row takes 1024 bytes, then setting FetchSize to 102400 takes just one server round-trip to fetch the hundred rows. For the same query, if the FetchSize is set to 10240, it takes 10 server round-trips to retrieve 100 rows. If the application requires all the rows to be fetched from the result set, the first scenario is faster than the second. However, if the application requires just the first 10 rows from the result set, the second scenario can perform better since it only fetches 10 rows and not 100 rows.

Using the RowSize Property

The RowSize property of the OracleCommand object is populated with the row size (in bytes) after an execution of a SELECT statement. The FetchSize property can then be set to a value relative to the RowSize by setting it to the product of RowSize and the number of rows to fetch for each server round-trip.

For example, setting the FetchSize to RowSize * 10 forces the OracleDataReader to fetch exactly 10 rows for each server round-trip. Note that the RowSize does not change due to the data length in each individual columns. Instead, the RowSize is determined strictly from the metadata information of the database table(s) that the SELECT is executed against.

The RowSize property can be used to set the FetchSize at design time or at runtime as described in the following sections.

Setting FetchSize Value at Design Time

If the row size for a particular SELECT statement is already known from a previous execution, FetchSize of the OracleCommand can be set at design time to the product of that row size and the number of rows the application wishes to fetch for each server round-trip. The FetchSize value set on the OracleCommand object is inherited by the OracleDataReader that is created by the ExecuteReader method invocation on the OracleCommand. Rather than setting the FetchSize on the OracleCommand, the FetchSize can also be set on the OracleDataReader directly. In either case, the FetchSize is set at design time without accessing the RowSize property value at runtime.

Setting FetchSize Value at Runtime

Applications that do not know the row size at design time can use the RowSize property of the OracleCommand object to set the FetchSize property of the OracleDataReader object. The RowSize property provides a dynamic way of setting the FetchSize property based on the size of a row.

After an OracleDataReader object is obtained by invoking the ExecuteReader method on the OracleCommand, the RowSize property is populated with the size of the row (in bytes). By using the RowSize property, the application can dynamically set the FetchSize property of the OracleDataReader to the product of the RowSize property value and the number of rows the application wishes to fetch for each server round-trip. In this scenario, the FetchSize is set by accessing the RowSize property at runtime.