| Oracle® Data Provider for .NET Developer's Guide 10g Release 1 (10.1) Part Number B10117-01 |
|
|
View PDF |
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:
The OracleDataReader provides two types of typed 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.
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
|
CLOB |
System.String |
GetString
|
DATE |
System.DateTime |
GetDateTime |
INTERVAL(DS) |
System.Interval |
GetTimeSpan |
INTERVAL (YM) |
System.Interval |
GetTimeSpan |
LONG |
System.String |
GetString
|
LONG RAW |
System.Byte[] |
GetBytes |
NCHAR |
System.String |
GetString
|
NCLOB |
System.String |
GetString
|
NUMBER |
System.Decimal |
GetDecimal |
NVARCHAR2 |
System.String |
GetString
|
RAW |
System.Byte[] |
GetBytes |
ROWID |
System.String |
GetString
|
TIMESTAMP |
System.TimeStamp |
GetTimeStamp |
TIMESTAMP WITH LOCAL TIME ZONE |
System.TimeStamp |
GetTimeStamp |
TIMESTAMP WITH TIME ZONE |
System.TimeStamp |
GetTimeStamp |
UROWID |
System.String |
GetString
|
VARCHAR2 |
System.String |
GetString
|
XMLType |
System.String
|
GetString
|
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.
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
|
GetOracleBlob
|
CHAR |
OracleString |
GetOracleString |
CLOB |
OracleClob
|
GetOracleClob
|
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 |
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.