OracleCommand.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / DataOracleClient / System / Data / OracleClient / OracleCommand.cs / 1 / OracleCommand.cs

                            //------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Data.OracleClient 
{
    using System; 
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    using System.Data.Common; 
    using System.Data.ProviderBase;
    using System.Data.SqlTypes; 
    using System.Diagnostics; 
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices; 
    using System.Text;

    [
    DefaultEvent("RecordsAffected"), 
    ToolboxItem(true),
    Designer("Microsoft.VSDesigner.Data.VS.OracleCommandDesigner, " + AssemblyRef.MicrosoftVSDesigner) 
    ] 
    sealed public class OracleCommand : DbCommand, ICloneable {
        private static int          _objectTypeCount; // Bid counter 
        internal readonly int       _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);

        private string              _commandText;
        private CommandType         _commandType; 
        private UpdateRowSource     _updatedRowSource = UpdateRowSource.Both;
        private bool                _designTimeInvisible; 
        private OracleConnection    _connection; 

        private OciStatementHandle  _preparedStatementHandle; 
        private int                 _preparedAtCloseCount;  // The close count of the connection; used to decide if we're zombied

        private OracleParameterCollection    _parameterCollection;
 
        private OCI.STMT            _statementType;         // set by the Execute method, so it's only valid after that.
 
        private OracleTransaction   _transaction; 

        // Construct an "empty" command 
        public OracleCommand() : base() {
            GC.SuppressFinalize(this);
        }
 
        // Construct a command from a command text
        public OracleCommand(string commandText) : this() { 
            CommandText = commandText; 
        }
 
        // Construct a command from a command text and a connection object
        public OracleCommand(string commandText, OracleConnection connection) : this() {
            CommandText = commandText;
            Connection = connection; 
        }
 
        // Construct a command from a command text, a connection object and a transaction 
        public OracleCommand(string commandText, OracleConnection connection, OracleTransaction tx) : this() {
            CommandText = commandText; 
            Connection = connection;
            Transaction = tx;
        }
 
        // (internal) Construct from an existing Command object (copy constructor)
        private OracleCommand(OracleCommand command) : this() { 
            CommandText = command.CommandText; 
            CommandType = command.CommandType;
            Connection = command.Connection; 
            DesignTimeVisible = command.DesignTimeVisible;
            UpdatedRowSource = command.UpdatedRowSource;
            Transaction = command.Transaction;
 
            if (null != command._parameterCollection && 0 < command._parameterCollection.Count) {
                OracleParameterCollection parameters = Parameters; 
 
                foreach(ICloneable parameter in command.Parameters) {
                    parameters.Add(parameter.Clone()); 
                }
            }
        }
 

        [ 
        ResCategoryAttribute(Res.OracleCategory_Data), 
        DefaultValue(""),
        ResDescriptionAttribute(Res.DbCommand_CommandText), 
        RefreshProperties(RefreshProperties.All),
        Editor("Microsoft.VSDesigner.Data.Oracle.Design.OracleCommandTextEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing)
        ]
        override public string CommandText { 
            get {
                string value = _commandText; 
                return ((null != value) ? value : ADP.StrEmpty); 
            }
            set { 
                if (Bid.TraceOn) {
                    Bid.Trace(" %d#, '", ObjectID);
                    Bid.PutStr(value); // Use PutStr to write out entire string
                    Bid.Trace("'\n"); 
                }
                if (0 != ADP.SrcCompare(_commandText, value)) { 
                    PropertyChanging(); 
                    _commandText = value;
                } 
            }
        }

        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        EditorBrowsableAttribute(EditorBrowsableState.Never), 
        ResCategoryAttribute(Res.OracleCategory_Data),
        ResDescriptionAttribute(Res.DbCommand_CommandTimeout), 
        ]
        public override int CommandTimeout {
            get {
                return 0; 
            }
            set { 
            } 
        }
 
        public void ResetCommandTimeout() { // V1.2.3300
        }

        private bool ShouldSerializeCommandTimeout() { // V1.2.3300 
            return false;
        } 
 
        [
        ResCategoryAttribute(Res.OracleCategory_Data), 
        DefaultValue(System.Data.CommandType.Text),
        ResDescriptionAttribute(Res.DbCommand_CommandType),
        RefreshProperties(RefreshProperties.All)
        ] 
        override public CommandType CommandType {
            get { 
                CommandType cmdType = _commandType; 
                return ((0 != cmdType) ? cmdType : CommandType.Text);
            } 
            set {
                if (_commandType != value) {
                    switch(value) {
                    case CommandType.StoredProcedure: 
                    case CommandType.Text:
                        PropertyChanging(); 
                        _commandType = value; 
                        break;
 
                    case CommandType.TableDirect:
                        throw ADP.NoOptimizedDirectTableAccess();

                    default: 
                        throw ADP.InvalidCommandType(value);
                    } 
                } 
            }
        } 

        [
        ResCategoryAttribute(Res.OracleCategory_Behavior),
        DefaultValue(null), 
        ResDescriptionAttribute(Res.DbCommand_Connection),
        Editor("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing) 
        ] 
        new public OracleConnection Connection {
            get { 
                return _connection;
            }
            set {
                if (_connection != value) { 
                    PropertyChanging();
                    _connection = value; 
                } 
            }
        } 

        private bool ConnectionIsClosed {
            //  TRUE when the parent connection object has been closed
            get { 
                OracleConnection conn = Connection;
                return (null == conn) || (ConnectionState.Closed == conn.State); 
            } 
        }
 
        override protected DbConnection DbConnection { // V1.2.3300
            get {
                return Connection;
            } 
            set {
                Connection = (OracleConnection)value; 
            } 
        }
 
        override protected DbParameterCollection DbParameterCollection { // V1.2.3300
            get {
                return Parameters;
            } 
        }
 
        override protected DbTransaction DbTransaction { // V1.2.3300 
            get {
                return Transaction; 
            }
            set {
                Transaction = (OracleTransaction)value;
            } 
        }
 
        // @devnote: By default, the cmd object is visible on the design surface (i.e. VS7 Server Tray) 
        // to limit the number of components that clutter the design surface,
        // when the DataAdapter design wizard generates the insert/update/delete commands it will 
        // set the DesignTimeVisible property to false so that cmds won't appear as individual objects
        [
        DefaultValue(true),
        DesignOnly(true), 
        Browsable(false),
        EditorBrowsableAttribute(EditorBrowsableState.Never), 
        ] 
        public override bool DesignTimeVisible { // V1.2.3300, XXXCommand V1.0.5000
            get { 
                return !_designTimeInvisible;
            }
            set {
                _designTimeInvisible = !value; 
                TypeDescriptor.Refresh(this); // VS7 208845
            } 
        } 

        private OciEnvironmentHandle EnvironmentHandle { 
            //  Simplify getting the EnvironmentHandle
            get {
                return _connection.EnvironmentHandle;
            } 
        }
 
        private OciErrorHandle ErrorHandle { 
            //  Every OCI call needs an error handle, so make it available internally.
            get { 
                return _connection.ErrorHandle;
            }
        }
 
        internal int ObjectID {
            get { 
                return _objectID; 
            }
        } 

        [
        ResCategoryAttribute(Res.OracleCategory_Data),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        ResDescriptionAttribute(Res.DbCommand_Parameters)
        ] 
        new public OracleParameterCollection Parameters { 
            get {
                if (null == _parameterCollection) { 
                    _parameterCollection = new OracleParameterCollection();
                }
                return _parameterCollection;
            } 
        }
 
        internal string StatementText { 
            //  Combine the CommandType and CommandText into the statement that
            //  needs to be passed to Oracle. 
            get {
                string statementText = null;
                string commandText = CommandText;
 
                if (ADP.IsEmpty(commandText)) {
                    throw ADP.NoCommandText(); 
                } 
                switch(CommandType) {
                case CommandType.StoredProcedure: { 
                    StringBuilder builder = new StringBuilder();

                    builder.Append("begin ");
 
                    int     parameterCount = Parameters.Count;
                    int     parameterUsed = 0; 
 
                    // Look for the return value:
                    for (int i=0; i < parameterCount; ++i) { 
                        OracleParameter parameter = Parameters[i];

                        if (ADP.IsDirection(parameter, ParameterDirection.ReturnValue)) {
                            builder.Append(":"); 
                            builder.Append(parameter.ParameterName);
                            builder.Append(" := "); 
                        } 
                    }
 
                    builder.Append(commandText);

                    string  separator = "(";
 
                    for (int i=0; i < parameterCount; ++i) {
                        OracleParameter parameter = Parameters[i]; 
 
                        if (ADP.IsDirection(parameter, ParameterDirection.ReturnValue)) {
                            continue;   // already did this one... 
                        }
                        if ( !ADP.IsDirection(parameter, ParameterDirection.Output) && null == parameter.Value) {
                            continue;   // don't include parameters where the user asks for the default value.
                        } 
                        // If the input-only parameter value is C# null, that's our "clue" that they
                        // wish to use the default value. 
                        if (null != parameter.Value || ADP.IsDirection(parameter, ParameterDirection.Output)) { 
                            builder.Append(separator);
                            separator = ", "; 
                            parameterUsed++;

                            builder.Append(parameter.ParameterName);    //
                            builder.Append("=>:"); 
                            builder.Append(parameter.ParameterName);
                        } 
                    } 

                    if (0 != parameterUsed) 
                        builder.Append("); end;");
                    else
                        builder.Append("; end;");
 
                    statementText = builder.ToString();
                    } 
                    break; 

                case CommandType.Text: 
                    statementText = commandText;
                    break;

                default: 
                    Debug.Assert(false, "command type of "+CommandType+" is not supported");
                    break; 
                } 
                return statementText;
            } 
        }

        private OciServiceContextHandle ServiceContextHandle {
            //  Simplify getting the ServiceContextHandle 
            get {
                return _connection.ServiceContextHandle; 
            } 
        }
        internal OCI.STMT StatementType { 
            get {
                return _statementType;
            }
        } 

        [ 
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        ResDescriptionAttribute(Res.DbCommand_Transaction) 
        ]
        new public OracleTransaction Transaction {
            //  Apparently, Yukon intends to move transaction support to the command
            //  object and has requested that IDbCommand have a transaction property 
            //  to support that.
            get { 
                // if the transaction object has been zombied, just return null 
                if ((null != _transaction) && (null == _transaction.Connection)) { // MDAC 72720
                    _transaction = null; 
                }
                return _transaction;
            }
            set { 
                _transaction = value;
            } 
        } 

        [ 
        DefaultValue(System.Data.UpdateRowSource.Both),
        ResCategoryAttribute(Res.DataCategory_Update),
        ResDescriptionAttribute(Res.DbCommand_UpdatedRowSource),
        ] 
        override public UpdateRowSource UpdatedRowSource { // V1.2.3300, XXXCommand V1.0.5000
            get { 
                return _updatedRowSource; 
            }
            set { 
                switch(value) { // @perfnote: Enum.IsDefined
                case UpdateRowSource.None:
                case UpdateRowSource.OutputParameters:
                case UpdateRowSource.FirstReturnedRecord: 
                case UpdateRowSource.Both:
                    _updatedRowSource = value; 
                    break; 
                default:
                    throw ADP.InvalidUpdateRowSource(value); 
                }
            }
        }
 
        // Cancel is supposed to be multi-thread safe.
        // It doesn't make sense to verify the connection exists or that it is open during cancel 
        // because immediately after checkin the connection can be closed or removed via another thread. 
        //
        override public void Cancel() { 
            // According to [....]: Cancel is meant to cancel firehose cursors only,
            // not to cancel the execution of a statement.  Given that for Oracle, you
            // don't need to tell the server you don't want any more results, it would
            // seem that this is unnecessary, so I'm commenting it out until someone 
            // comes up with a reason for it.
            IntPtr hscp; 
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try {
#if UNUSED 
                int rc = TracedNativeMethods.OCIBreak(
                    ServiceContextHandle.GetHandle(),
                    ErrorHandle.Handle
                ); 

                if (0 != rc) { 
                    Connection.CheckError(ErrorHandle, rc); 
                }
#endif // 
            }
            finally {
                Bid.ScopeLeave(ref hscp);
            } 
        }
 
        public object Clone() { 
            OracleCommand clone = new OracleCommand(this);
            Bid.Trace(" %d#, clone=%d#\n", ObjectID, clone.ObjectID); 
            return clone;
        }

        new public OracleParameter CreateParameter() { 
            return new OracleParameter();
        } 
 
        override protected DbParameter CreateDbParameter() {
            return CreateParameter(); 
        }

        internal string Execute(OciStatementHandle statementHandle, CommandBehavior behavior, out ArrayList resultParameterOrdinals) {
            OciRowidDescriptor  temp1; 
            return Execute(statementHandle, behavior, false, out temp1, out resultParameterOrdinals);
        } 
 
        internal string Execute(OciStatementHandle statementHandle, CommandBehavior behavior, bool needRowid, out OciRowidDescriptor rowidDescriptor, out ArrayList resultParameterOrdinals) {
            //  common routine used to execute all statements 

            if (ConnectionIsClosed) {
                throw ADP.ClosedConnectionError();
            } 
            // throw if the connection is in a transaction but there is no
            // locally assigned transaction object 
            if ((null == _transaction) && (null != Connection.Transaction)) { 
                throw ADP.TransactionRequired();
            } 
            // if we have a transaction, check to ensure that the active
            // connection property matches the connection associated with
            // the transaction
            if ((null != _transaction) && (null != _transaction.Connection) && (Connection != _transaction.Connection)) { 
                throw ADP.TransactionConnectionMismatch();
            } 
            rowidDescriptor = null; 

            // if the connection has a command but it went out of scope, we need 
            // to roll it back.  We do this here instead of in the transaction
            // objects finalizer because it doesn't really matter when it gets
            // done, just as long as it is before the next command executes, and
            // it's easier to do it in the command object, than in the object 
            // that is being finalized.
            Connection.RollbackDeadTransaction(); 
 
            int                         rc = 0;
            NativeBuffer                parameterBuffer = null; 
            bool                        mustRelease = false;
            bool[]                      mustReleaseBindHandle = null;
            SafeHandle[]                handleToBind = null;
            short                       tempub2; 
            int                         iterations;
            OracleParameterBinding[]    parameterBinding = null; 
            string                      statementText = null; 

            resultParameterOrdinals = null; 

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
 
                // If we've already sent the statement to the server, then we don't need
                // to prepare it again... 
                if (_preparedStatementHandle != statementHandle) { 
                    statementText = StatementText;
 
                    rc = TracedNativeMethods.OCIStmtPrepare(
                                            statementHandle,
                                            ErrorHandle,
                                            statementText, 
                                            OCI.SYNTAX.OCI_NTV_SYNTAX,
                                            OCI.MODE.OCI_DEFAULT, 
                                            Connection 
                                            );
 
                    if (0 != rc) {
                        Connection.CheckError(ErrorHandle, rc);
                    }
                } 

                // Figure out what kind of statement we're dealing with and pick the 
                // appropriate iteration count. 
                statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_STMT_TYPE, out tempub2, ErrorHandle);
                _statementType = (OCI.STMT)tempub2; 

                if (OCI.STMT.OCI_STMT_SELECT != _statementType) {
                    iterations = 1;
                } 
                else {
                    iterations = 0; 
 
                    if (CommandBehavior.SingleRow != behavior) {
                        // We're doing our own "prefetching" to avoid double copies, so we 
                        // need to turn off Oracle's or it won't really help.
                        statementHandle.SetAttribute(OCI.ATTR.OCI_ATTR_PREFETCH_ROWS,   0,  ErrorHandle);
                        statementHandle.SetAttribute(OCI.ATTR.OCI_ATTR_PREFETCH_MEMORY, 0,  ErrorHandle);
                    } 
                }
 
                // Pick the execution mode we need to use 
                OCI.MODE        executeMode = OCI.MODE.OCI_DEFAULT;
 
                if (0 == iterations) {
                    if (IsBehavior(behavior, CommandBehavior.SchemaOnly)) {
                        // If we're only supposed to "describe" the data columns for the rowset, then
                        // use the describe only execute mode 
                        executeMode |= OCI.MODE.OCI_DESCRIBE_ONLY;
                    } 
                } 
                else {
                    if (TransactionState.AutoCommit == _connection.TransactionState) { 
                        // If we're in autocommit mode, then we have to tell Oracle to automatically
                        // commit the transaction it automatically created.
                        executeMode |= OCI.MODE.OCI_COMMIT_ON_SUCCESS;
                    } 
                    else if (TransactionState.GlobalStarted != _connection.TransactionState) {
                        // If we're not in "auto commit mode" then we can presume that Oracle 
                        // will automatically start a transaction, so we need to keep track 
                        // of that.
                        _connection.TransactionState = TransactionState.LocalStarted; 
                    }
                }

                    // Bind all the parameter values, unless we're just looking for schema info 
                if (0 == (executeMode & OCI.MODE.OCI_DESCRIBE_ONLY)) {
                    if (null != _parameterCollection && _parameterCollection.Count > 0) { 
                        int parameterBufferLength = 0; 
                        int length = _parameterCollection.Count;
 
                        mustReleaseBindHandle  = new bool[length];
                        handleToBind = new SafeHandle[length];
                        parameterBinding = new OracleParameterBinding[length];
 
                        for (int i = 0; i < length; ++i) {
                            parameterBinding[i] = new OracleParameterBinding(this, _parameterCollection[i]); 
                            parameterBinding[i].PrepareForBind( _connection, ref parameterBufferLength ); 

                            // If this is a ref cursor parameter that we're supposed to include 
                            // in the data reader, then add it to our list of those.
                            if (OracleType.Cursor == _parameterCollection[i].OracleType
                                || 0 < _parameterCollection[i].CommandSetResult) {
                                if (null == resultParameterOrdinals) { 
                                    resultParameterOrdinals = new ArrayList();
                                } 
                                resultParameterOrdinals.Add(i); 
                            }
                        } 

                        parameterBuffer = new NativeBuffer_ParameterBuffer(parameterBufferLength);

                        parameterBuffer.DangerousAddRef(ref mustRelease); 

                        for (int i = 0; i < length; ++i) { 
                            parameterBinding[i].Bind( statementHandle, parameterBuffer, _connection, ref mustReleaseBindHandle[i], ref handleToBind[i] ); 
                        }
                    } 
                }

                // OK, now go ahead and execute
                rc = TracedNativeMethods.OCIStmtExecute( 
                                        ServiceContextHandle,   // svchp
                                        statementHandle,        // stmtp 
                                        ErrorHandle,            // errhp 
                                        iterations,             // iters
                                        executeMode             // mode 
                                        );

                if (0 != rc)
                    Connection.CheckError(ErrorHandle, rc); 

                // and now, create the output parameter values 
                if (null != parameterBinding) { 
                    int length = parameterBinding.Length;
 
                    for (int i = 0; i < length; ++i) {
                        parameterBinding[i].PostExecute( parameterBuffer, _connection );
                        parameterBinding[i].Dispose();
                        parameterBinding[i] = null; 
                    }
                    parameterBinding = null; 
                } 

                if (needRowid && 0 == (executeMode & OCI.MODE.OCI_DESCRIBE_ONLY)) { 
                    switch (_statementType) {
                        case OCI.STMT.OCI_STMT_UPDATE:
                        case OCI.STMT.OCI_STMT_DELETE:
                        case OCI.STMT.OCI_STMT_INSERT: 
                            rowidDescriptor = statementHandle.GetRowid(EnvironmentHandle, ErrorHandle);
                            break; 
 
                        default:
                            rowidDescriptor = null; 
                            break;
                    }
                }
            } 
            finally {
                if (mustRelease) { 
                    parameterBuffer.DangerousRelease(); 
                }
 
                if (null != parameterBuffer) {
                    // We're done with these, get rid of them.
                    parameterBuffer.Dispose();
                    parameterBuffer = null; 
                }
 
                // and now, release/free the output parameter values 
                if (null != parameterBinding) {
                    int length = parameterBinding.Length; 

                    for (int i = 0; i < length; ++i) {
                        if (null != parameterBinding[i]) {
                            parameterBinding[i].Dispose(); 
                            parameterBinding[i] = null;
                        } 
                    } 
                    parameterBinding = null;
                } 

                if (null != mustReleaseBindHandle && null != handleToBind) {
                    int length = mustReleaseBindHandle.Length;
 
                    for (int i = 0; i < length; ++i) {
                        if (mustReleaseBindHandle[i]) { 
                            handleToBind[i].DangerousRelease(); 
                        }
                    } 
                }
            }
            return statementText;
        } 

        override protected DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { 
            return ExecuteReader(behavior); 
        }
 
        override public int ExecuteNonQuery() {
            OracleConnection.ExecutePermission.Demand();
            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try {
                OciRowidDescriptor  temp = null; 
                int         result = ExecuteNonQueryInternal(false, out temp); 
                OciHandle.SafeDispose(ref temp);    // shouldn't be necessary, but just in case...
                return result; 
            }
            finally {
                Bid.ScopeLeave(ref hscp);
            } 
        }
 
        private int ExecuteNonQueryInternal(bool needRowid, out OciRowidDescriptor rowidDescriptor) { 
            OciStatementHandle  statementHandle = null;
            int         rowcount = -1; 

            try {
                try {
                    ArrayList resultParameterOrdinals = new ArrayList(); 
                    statementHandle = GetStatementHandle();
                    Execute( statementHandle, CommandBehavior.Default, needRowid, out rowidDescriptor, out resultParameterOrdinals ); 
 
                    if (null != resultParameterOrdinals) {
                        rowcount = 0; 

                        foreach (int resultParameterOrdinal in resultParameterOrdinals) {
                            OracleParameter resultParameter = _parameterCollection[resultParameterOrdinal];
 
                            if (OracleType.Cursor != resultParameter.OracleType) {
                                Debug.Assert(0 < resultParameter.CommandSetResult, "non-ref cursor, non recordsaffected parameter?"); 
                                rowcount += (int)resultParameter.Value; 
                            }
                        } 
                    }
                    else {
                        if (OCI.STMT.OCI_STMT_SELECT != _statementType) {
                            statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_ROW_COUNT, out rowcount, ErrorHandle); 
                        }
                    } 
                } 
                finally {
                    if (null != statementHandle) 
                        ReleaseStatementHandle(statementHandle);
                }
            }
            catch { // Prevent exception filters from running in our space 
                throw;
            } 
 
            return rowcount;
        } 

        public int ExecuteOracleNonQuery(out OracleString rowid) {
            OracleConnection.ExecutePermission.Demand();
 
            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try { 
                OciRowidDescriptor  rowidDescriptor = null;
                int         result = ExecuteNonQueryInternal(true, out rowidDescriptor); 
                rowid = GetPersistedRowid( Connection, rowidDescriptor );
                OciHandle.SafeDispose(ref rowidDescriptor);
                return result;
            } 
            finally {
                Bid.ScopeLeave(ref hscp); 
            } 
        }
 
        public object ExecuteOracleScalar() {
            OracleConnection.ExecutePermission.Demand();

            IntPtr hscp; 
            Bid.ScopeEnter(out hscp, " %d#", ObjectID);
            try { 
                OciRowidDescriptor  temp = null; 
                object      result = ExecuteScalarInternal(false, false, out temp);
                OciHandle.SafeDispose(ref temp);    // shouldn't be necessary, but just in case... 
                return result;
            }
            finally {
                Bid.ScopeLeave(ref hscp); 
            }
        } 
 
        new public OracleDataReader ExecuteReader() {
            return ExecuteReader(CommandBehavior.Default); 
        }

        new public OracleDataReader ExecuteReader(CommandBehavior behavior) {
            OracleConnection.ExecutePermission.Demand(); 
            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#, behavior=%d{ds.CommandBehavior}\n", ObjectID, (int)behavior); 
            try { 
                OciStatementHandle  statementHandle = null;;
                OracleDataReader    reader = null; 
                ArrayList           resultParameterOrdinals = null;

                 try {
                    statementHandle = GetStatementHandle(); 

                    string statementText = Execute( statementHandle, behavior, out resultParameterOrdinals); 
 

                    // We're about to handle the prepared statement handle (if there was one) 
                    // to the data reader object; so we can't really hold on to it any longer.
                    if (statementHandle == _preparedStatementHandle) {
                        // Don't dispose the handle, we still need it!  just make our reference to it null.
                        _preparedStatementHandle = null; 
                        //
                    } 
 
                    if (null == resultParameterOrdinals)
                        reader = new OracleDataReader(this, statementHandle, statementText, behavior); 
                    else
                        reader = new OracleDataReader(this, resultParameterOrdinals, statementText, behavior);
                }
                finally { 
                    // if we didn't hand the statement to a reader, then release it
                    if (null != statementHandle && (null == reader || null != resultParameterOrdinals)) { 
                        ReleaseStatementHandle(statementHandle); 
                    }
                } 
                return reader;
            }
            finally {
                Bid.ScopeLeave(ref hscp); 
            }
        } 
 
        override public object ExecuteScalar() {
            OracleConnection.ExecutePermission.Demand(); 

            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID);
            try { 
                OciRowidDescriptor  temp;
                object result = ExecuteScalarInternal(true, false, out temp); 
                OciHandle.SafeDispose(ref temp);    // shouldn't be necessary, but just in case... 
                return result;
            } 
            finally {
                Bid.ScopeLeave(ref hscp);
            }
        } 

        private object ExecuteScalarInternal(bool needCLStype, bool needRowid, out OciRowidDescriptor rowidDescriptor) { 
            OciStatementHandle  statementHandle = null; 
            object      result = null;
            int         rc = 0; 

             try {
                statementHandle = GetStatementHandle();
 
                ArrayList temp = new ArrayList();
 
                Execute( statementHandle, CommandBehavior.Default, needRowid, out rowidDescriptor, out temp ); 

                if (OCI.STMT.OCI_STMT_SELECT == _statementType) { 
                    // We only care about one column; Oracle will handle the fact that the
                    // rest aren't define so don't bother allocating and gathering more column
                    // information than we need.
                    OracleColumn    column = new OracleColumn(statementHandle, 0, ErrorHandle, _connection); 
                    int             columnBufferLength = 0;
                    bool            mustRelease = false; 
                    bool            mustReleaseBindHandle = false; 
                    SafeHandle      bindHandle = null;
 
                    column.Describe(ref columnBufferLength, _connection, ErrorHandle);

                    NativeBuffer_RowBuffer columnBuffer = new NativeBuffer_RowBuffer(columnBufferLength, 1);
 
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try { 
                        columnBuffer.DangerousAddRef(ref mustRelease); 

                        column.Bind(statementHandle, columnBuffer, ErrorHandle, 0); 
                        column.Rebind(_connection, ref mustReleaseBindHandle, ref bindHandle);

                        // Now fetch one row into the buffer we've provided
                        rc = TracedNativeMethods.OCIStmtFetch( 
                                                statementHandle,            // stmtp
                                                ErrorHandle,                // errhp 
                                                1,                          // crows 
                                                OCI.FETCH.OCI_FETCH_NEXT,   // orientation
                                                OCI.MODE.OCI_DEFAULT        // mode 
                                                );
                        if ((int)OCI.RETURNCODE.OCI_NO_DATA != rc) {
                            if (0 != rc)
                                Connection.CheckError(ErrorHandle, rc); 

 
                            // Ask the column for the object value (we need to get the Value from 
                            // the object to ensure that we have a URT type object, not an Oracle
                            // type object) 
                            if (needCLStype)
                                result = column.GetValue(columnBuffer);
                            else
                                result = column.GetOracleValue(columnBuffer); 
                        }
                    } 
                    finally { 
                        if (mustReleaseBindHandle) {
                            bindHandle.DangerousRelease(); 
                        }
                        if (mustRelease) {
                            columnBuffer.DangerousRelease();
                        } 
                    }
                    GC.KeepAlive(column); 
                } 
            }
            finally { 
                if (null != statementHandle) {
                    ReleaseStatementHandle(statementHandle);
                }
            } 
            return result;
        } 
 
        static internal OracleString GetPersistedRowid(OracleConnection connection, OciRowidDescriptor rowidHandle) {
            //  This method returns an OracleString that holds the base64 string 
            //  representation of the rowid, which can be persisted past the lifetime
            //  of this process.

            OracleString result = OracleString.Null; 

            if (null == rowidHandle) 
                goto done;  // null if there isn't a rowid! 

            OciErrorHandle  errorHandle = connection.ErrorHandle; 
            NativeBuffer    rowidBuffer = connection.GetScratchBuffer(3970);
            bool            mustRelease = false;
            bool            mustReleaseRowidHandle = false;
            int             rc; 

            RuntimeHelpers.PrepareConstrainedRegions(); 
            try { 
                rowidBuffer.DangerousAddRef(ref mustRelease);
 
                if (OCI.ClientVersionAtLeastOracle9i) {
                    int bufferLength = rowidBuffer.Length;

                    rc = TracedNativeMethods.OCIRowidToChar(rowidHandle, 
                                                        rowidBuffer,
                                                        ref bufferLength, 
                                                        errorHandle 
                                                        );
                    if (0 != rc) { 
                        connection.CheckError(errorHandle, rc);
                    }
                    string stringValue = rowidBuffer.PtrToStringAnsi(0, bufferLength); // ROWID's always come back as Ansi...
 
                    result = new OracleString(stringValue);
                } 
                else { 
                    rowidHandle.DangerousAddRef(ref mustReleaseRowidHandle);
 
                    OciServiceContextHandle     serviceContextHandle = connection.ServiceContextHandle;

                    OciStatementHandle tempHandle = new OciStatementHandle(serviceContextHandle);
                    string          tempText = "begin :rowid := :rdesc; end;"; 
                    int             rdescIndicatorOffset= 0;
                    int             rdescLengthOffset   = 4; 
                    int             rdescValueOffset    = 8; 
                    int             rowidIndicatorOffset= 12;
                    int             rowidLengthOffset   = 16; 
                    int             rowidValueOffset    = 20;

                     try {
                        rc = TracedNativeMethods.OCIStmtPrepare( 
                                                tempHandle,
                                                errorHandle, 
                                                tempText, 
                                                OCI.SYNTAX.OCI_NTV_SYNTAX,
                                                OCI.MODE.OCI_DEFAULT, 
                                                connection
                                                );
                        if (0 != rc)
                            connection.CheckError(errorHandle, rc); 

                        IntPtr h1; 
                        IntPtr h2; 

                        // Need to clean these out, since we're re-using the scratch buffer, which 
                        // the prepare uses to convert the statement text.
                        rowidBuffer.WriteIntPtr(rdescValueOffset,       rowidHandle.DangerousGetHandle());
                        rowidBuffer.WriteInt32 (rdescIndicatorOffset,   0);
                        rowidBuffer.WriteInt32 (rdescLengthOffset,      4); 
                        rowidBuffer.WriteInt32 (rowidIndicatorOffset,   0);
                        rowidBuffer.WriteInt32 (rowidLengthOffset,      3950); 
 
                        rc = TracedNativeMethods.OCIBindByName(
                                        tempHandle, 
                                        out h1,
                                        errorHandle,
                                        "rowid",
                                        5, 
                                        rowidBuffer.DangerousGetDataPtr(rowidValueOffset),
                                        3950, 
                                        OCI.DATATYPE.VARCHAR2, 
                                        rowidBuffer.DangerousGetDataPtr(rowidIndicatorOffset),
                                        rowidBuffer.DangerousGetDataPtr(rowidLengthOffset), 
                                        OCI.MODE.OCI_DEFAULT
                                        );
                        if (0 != rc)
                            connection.CheckError(errorHandle, rc); 

                        rc = TracedNativeMethods.OCIBindByName( 
                                        tempHandle, 
                                        out h2,
                                        errorHandle, 
                                        "rdesc",
                                        5,
                                        rowidBuffer.DangerousGetDataPtr(rdescValueOffset),
                                        4, 
                                        OCI.DATATYPE.ROWID_DESC,
                                        rowidBuffer.DangerousGetDataPtr(rdescIndicatorOffset), 
                                        rowidBuffer.DangerousGetDataPtr(rdescLengthOffset), 
                                        OCI.MODE.OCI_DEFAULT
                                        ); 
                        if (0 != rc)
                            connection.CheckError(errorHandle, rc);

                        rc = TracedNativeMethods.OCIStmtExecute( 
                                                serviceContextHandle,   // svchp
                                                tempHandle,             // stmtp 
                                                errorHandle,            // errhp 
                                                1,                      // iters
                                                OCI.MODE.OCI_DEFAULT    // mode 
                                                );

                        if (0 != rc)
                            connection.CheckError(errorHandle, rc); 

                        if (rowidBuffer.ReadInt16(rowidIndicatorOffset) == (Int16)OCI.INDICATOR.ISNULL) 
                            goto done; 

                        result = new OracleString( 
                                                rowidBuffer,
                                                rowidValueOffset,
                                                rowidLengthOffset,
                                                MetaType.GetMetaTypeForType(OracleType.RowId), 
                                                connection,
                                                false,   // it's not unicode! 
                                                true 
                                                );
                        GC.KeepAlive(rowidHandle); 
                    }
                    finally {
                        OciHandle.SafeDispose(ref tempHandle);
                    } 
                }
            } 
            finally{ 
                if (mustReleaseRowidHandle) {
                    rowidHandle.DangerousRelease(); 
                }
                if (mustRelease) {
                    rowidBuffer.DangerousRelease();
                } 
            }
 
        done: 
            return result;
        } 

        private OciStatementHandle GetStatementHandle() {
            //  return either the prepared statement handle or a new one if nothign
            //  is prepared. 

            if (ConnectionIsClosed) { 
                throw ADP.ClosedConnectionError(); 
            }
            if (null != _preparedStatementHandle) { 
                // When we prepare the statement, we keep track of it's closed
                // count; if the connection has been closed since we prepared, then
                // the statement handle is no longer valid and must be tossed.
                if (_connection.CloseCount == _preparedAtCloseCount) { 
                    return _preparedStatementHandle;
                } 
                _preparedStatementHandle.Dispose(); 
                _preparedStatementHandle = null;
            } 
            return new OciStatementHandle(ServiceContextHandle);
        }

        static internal bool IsBehavior(CommandBehavior value, CommandBehavior condition) { 
            return (condition == (condition & value));
        } 
 
        override public void Prepare() {
            OracleConnection.ExecutePermission.Demand(); 

            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID);
            try { 

                if (ConnectionIsClosed) { 
                    throw ADP.ClosedConnectionError(); 
                }
                if (CommandType.Text == CommandType) { 
                    OciStatementHandle  preparedStatementHandle = GetStatementHandle();
                    int         preparedAtCloseCount = _connection.CloseCount;
                    string      statementText = StatementText;
 
                    int rc = TracedNativeMethods.OCIStmtPrepare(
                                                preparedStatementHandle, 
                                                ErrorHandle, 
                                                statementText,
                                                OCI.SYNTAX.OCI_NTV_SYNTAX, 
                                                OCI.MODE.OCI_DEFAULT,
                                                Connection
                                                );
 
                    if (0 != rc) {
                        Connection.CheckError(ErrorHandle, rc); 
                    } 
                    short   tempub2;
 
                    preparedStatementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_STMT_TYPE, out tempub2, ErrorHandle);
                    _statementType = (OCI.STMT)tempub2;

                    if (OCI.STMT.OCI_STMT_SELECT == _statementType) { 
                        rc = TracedNativeMethods.OCIStmtExecute(
                                            _connection.ServiceContextHandle, 
                                                                        // svchp 
                                            preparedStatementHandle,    // stmtp
                                            ErrorHandle,                // errhp 
                                            0,                          // iters
                                            OCI.MODE.OCI_DESCRIBE_ONLY  // mode
                                            );
 
                        if (0 != rc) {
                            Connection.CheckError(ErrorHandle, rc); 
                        } 
                    }
 
                    if (preparedStatementHandle != _preparedStatementHandle) {
                        OciHandle.SafeDispose(ref _preparedStatementHandle);
                    }
                    _preparedStatementHandle = preparedStatementHandle; 
                    _preparedAtCloseCount = preparedAtCloseCount;
 
                } 
                else if (null != _preparedStatementHandle) {
                    OciHandle.SafeDispose(ref _preparedStatementHandle); 
                }
            }
            finally {
                Bid.ScopeLeave(ref hscp); 
            }
        } 
 
        private void PropertyChanging() {
            //  common routine used to get rid of a statement handle; it disposes 
            //  of the handle unless it's the prepared handle

            if (null != _preparedStatementHandle) {
                _preparedStatementHandle.Dispose(); // the existing prepared statement is no longer valid 
                _preparedStatementHandle = null;
            } 
        } 

        private void ReleaseStatementHandle (OciStatementHandle statementHandle) { 
            //  common routine used to get rid of a statement handle; it disposes
            //  of the handle unless it's the prepared handle

            if (ConnectionState.Closed != Connection.State && _preparedStatementHandle != statementHandle) { 
                OciHandle.SafeDispose(ref statementHandle);
            } 
        } 
    };
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Data.OracleClient 
{
    using System; 
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    using System.Data.Common; 
    using System.Data.ProviderBase;
    using System.Data.SqlTypes; 
    using System.Diagnostics; 
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices; 
    using System.Text;

    [
    DefaultEvent("RecordsAffected"), 
    ToolboxItem(true),
    Designer("Microsoft.VSDesigner.Data.VS.OracleCommandDesigner, " + AssemblyRef.MicrosoftVSDesigner) 
    ] 
    sealed public class OracleCommand : DbCommand, ICloneable {
        private static int          _objectTypeCount; // Bid counter 
        internal readonly int       _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);

        private string              _commandText;
        private CommandType         _commandType; 
        private UpdateRowSource     _updatedRowSource = UpdateRowSource.Both;
        private bool                _designTimeInvisible; 
        private OracleConnection    _connection; 

        private OciStatementHandle  _preparedStatementHandle; 
        private int                 _preparedAtCloseCount;  // The close count of the connection; used to decide if we're zombied

        private OracleParameterCollection    _parameterCollection;
 
        private OCI.STMT            _statementType;         // set by the Execute method, so it's only valid after that.
 
        private OracleTransaction   _transaction; 

        // Construct an "empty" command 
        public OracleCommand() : base() {
            GC.SuppressFinalize(this);
        }
 
        // Construct a command from a command text
        public OracleCommand(string commandText) : this() { 
            CommandText = commandText; 
        }
 
        // Construct a command from a command text and a connection object
        public OracleCommand(string commandText, OracleConnection connection) : this() {
            CommandText = commandText;
            Connection = connection; 
        }
 
        // Construct a command from a command text, a connection object and a transaction 
        public OracleCommand(string commandText, OracleConnection connection, OracleTransaction tx) : this() {
            CommandText = commandText; 
            Connection = connection;
            Transaction = tx;
        }
 
        // (internal) Construct from an existing Command object (copy constructor)
        private OracleCommand(OracleCommand command) : this() { 
            CommandText = command.CommandText; 
            CommandType = command.CommandType;
            Connection = command.Connection; 
            DesignTimeVisible = command.DesignTimeVisible;
            UpdatedRowSource = command.UpdatedRowSource;
            Transaction = command.Transaction;
 
            if (null != command._parameterCollection && 0 < command._parameterCollection.Count) {
                OracleParameterCollection parameters = Parameters; 
 
                foreach(ICloneable parameter in command.Parameters) {
                    parameters.Add(parameter.Clone()); 
                }
            }
        }
 

        [ 
        ResCategoryAttribute(Res.OracleCategory_Data), 
        DefaultValue(""),
        ResDescriptionAttribute(Res.DbCommand_CommandText), 
        RefreshProperties(RefreshProperties.All),
        Editor("Microsoft.VSDesigner.Data.Oracle.Design.OracleCommandTextEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing)
        ]
        override public string CommandText { 
            get {
                string value = _commandText; 
                return ((null != value) ? value : ADP.StrEmpty); 
            }
            set { 
                if (Bid.TraceOn) {
                    Bid.Trace(" %d#, '", ObjectID);
                    Bid.PutStr(value); // Use PutStr to write out entire string
                    Bid.Trace("'\n"); 
                }
                if (0 != ADP.SrcCompare(_commandText, value)) { 
                    PropertyChanging(); 
                    _commandText = value;
                } 
            }
        }

        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        EditorBrowsableAttribute(EditorBrowsableState.Never), 
        ResCategoryAttribute(Res.OracleCategory_Data),
        ResDescriptionAttribute(Res.DbCommand_CommandTimeout), 
        ]
        public override int CommandTimeout {
            get {
                return 0; 
            }
            set { 
            } 
        }
 
        public void ResetCommandTimeout() { // V1.2.3300
        }

        private bool ShouldSerializeCommandTimeout() { // V1.2.3300 
            return false;
        } 
 
        [
        ResCategoryAttribute(Res.OracleCategory_Data), 
        DefaultValue(System.Data.CommandType.Text),
        ResDescriptionAttribute(Res.DbCommand_CommandType),
        RefreshProperties(RefreshProperties.All)
        ] 
        override public CommandType CommandType {
            get { 
                CommandType cmdType = _commandType; 
                return ((0 != cmdType) ? cmdType : CommandType.Text);
            } 
            set {
                if (_commandType != value) {
                    switch(value) {
                    case CommandType.StoredProcedure: 
                    case CommandType.Text:
                        PropertyChanging(); 
                        _commandType = value; 
                        break;
 
                    case CommandType.TableDirect:
                        throw ADP.NoOptimizedDirectTableAccess();

                    default: 
                        throw ADP.InvalidCommandType(value);
                    } 
                } 
            }
        } 

        [
        ResCategoryAttribute(Res.OracleCategory_Behavior),
        DefaultValue(null), 
        ResDescriptionAttribute(Res.DbCommand_Connection),
        Editor("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing) 
        ] 
        new public OracleConnection Connection {
            get { 
                return _connection;
            }
            set {
                if (_connection != value) { 
                    PropertyChanging();
                    _connection = value; 
                } 
            }
        } 

        private bool ConnectionIsClosed {
            //  TRUE when the parent connection object has been closed
            get { 
                OracleConnection conn = Connection;
                return (null == conn) || (ConnectionState.Closed == conn.State); 
            } 
        }
 
        override protected DbConnection DbConnection { // V1.2.3300
            get {
                return Connection;
            } 
            set {
                Connection = (OracleConnection)value; 
            } 
        }
 
        override protected DbParameterCollection DbParameterCollection { // V1.2.3300
            get {
                return Parameters;
            } 
        }
 
        override protected DbTransaction DbTransaction { // V1.2.3300 
            get {
                return Transaction; 
            }
            set {
                Transaction = (OracleTransaction)value;
            } 
        }
 
        // @devnote: By default, the cmd object is visible on the design surface (i.e. VS7 Server Tray) 
        // to limit the number of components that clutter the design surface,
        // when the DataAdapter design wizard generates the insert/update/delete commands it will 
        // set the DesignTimeVisible property to false so that cmds won't appear as individual objects
        [
        DefaultValue(true),
        DesignOnly(true), 
        Browsable(false),
        EditorBrowsableAttribute(EditorBrowsableState.Never), 
        ] 
        public override bool DesignTimeVisible { // V1.2.3300, XXXCommand V1.0.5000
            get { 
                return !_designTimeInvisible;
            }
            set {
                _designTimeInvisible = !value; 
                TypeDescriptor.Refresh(this); // VS7 208845
            } 
        } 

        private OciEnvironmentHandle EnvironmentHandle { 
            //  Simplify getting the EnvironmentHandle
            get {
                return _connection.EnvironmentHandle;
            } 
        }
 
        private OciErrorHandle ErrorHandle { 
            //  Every OCI call needs an error handle, so make it available internally.
            get { 
                return _connection.ErrorHandle;
            }
        }
 
        internal int ObjectID {
            get { 
                return _objectID; 
            }
        } 

        [
        ResCategoryAttribute(Res.OracleCategory_Data),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        ResDescriptionAttribute(Res.DbCommand_Parameters)
        ] 
        new public OracleParameterCollection Parameters { 
            get {
                if (null == _parameterCollection) { 
                    _parameterCollection = new OracleParameterCollection();
                }
                return _parameterCollection;
            } 
        }
 
        internal string StatementText { 
            //  Combine the CommandType and CommandText into the statement that
            //  needs to be passed to Oracle. 
            get {
                string statementText = null;
                string commandText = CommandText;
 
                if (ADP.IsEmpty(commandText)) {
                    throw ADP.NoCommandText(); 
                } 
                switch(CommandType) {
                case CommandType.StoredProcedure: { 
                    StringBuilder builder = new StringBuilder();

                    builder.Append("begin ");
 
                    int     parameterCount = Parameters.Count;
                    int     parameterUsed = 0; 
 
                    // Look for the return value:
                    for (int i=0; i < parameterCount; ++i) { 
                        OracleParameter parameter = Parameters[i];

                        if (ADP.IsDirection(parameter, ParameterDirection.ReturnValue)) {
                            builder.Append(":"); 
                            builder.Append(parameter.ParameterName);
                            builder.Append(" := "); 
                        } 
                    }
 
                    builder.Append(commandText);

                    string  separator = "(";
 
                    for (int i=0; i < parameterCount; ++i) {
                        OracleParameter parameter = Parameters[i]; 
 
                        if (ADP.IsDirection(parameter, ParameterDirection.ReturnValue)) {
                            continue;   // already did this one... 
                        }
                        if ( !ADP.IsDirection(parameter, ParameterDirection.Output) && null == parameter.Value) {
                            continue;   // don't include parameters where the user asks for the default value.
                        } 
                        // If the input-only parameter value is C# null, that's our "clue" that they
                        // wish to use the default value. 
                        if (null != parameter.Value || ADP.IsDirection(parameter, ParameterDirection.Output)) { 
                            builder.Append(separator);
                            separator = ", "; 
                            parameterUsed++;

                            builder.Append(parameter.ParameterName);    //
                            builder.Append("=>:"); 
                            builder.Append(parameter.ParameterName);
                        } 
                    } 

                    if (0 != parameterUsed) 
                        builder.Append("); end;");
                    else
                        builder.Append("; end;");
 
                    statementText = builder.ToString();
                    } 
                    break; 

                case CommandType.Text: 
                    statementText = commandText;
                    break;

                default: 
                    Debug.Assert(false, "command type of "+CommandType+" is not supported");
                    break; 
                } 
                return statementText;
            } 
        }

        private OciServiceContextHandle ServiceContextHandle {
            //  Simplify getting the ServiceContextHandle 
            get {
                return _connection.ServiceContextHandle; 
            } 
        }
        internal OCI.STMT StatementType { 
            get {
                return _statementType;
            }
        } 

        [ 
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        ResDescriptionAttribute(Res.DbCommand_Transaction) 
        ]
        new public OracleTransaction Transaction {
            //  Apparently, Yukon intends to move transaction support to the command
            //  object and has requested that IDbCommand have a transaction property 
            //  to support that.
            get { 
                // if the transaction object has been zombied, just return null 
                if ((null != _transaction) && (null == _transaction.Connection)) { // MDAC 72720
                    _transaction = null; 
                }
                return _transaction;
            }
            set { 
                _transaction = value;
            } 
        } 

        [ 
        DefaultValue(System.Data.UpdateRowSource.Both),
        ResCategoryAttribute(Res.DataCategory_Update),
        ResDescriptionAttribute(Res.DbCommand_UpdatedRowSource),
        ] 
        override public UpdateRowSource UpdatedRowSource { // V1.2.3300, XXXCommand V1.0.5000
            get { 
                return _updatedRowSource; 
            }
            set { 
                switch(value) { // @perfnote: Enum.IsDefined
                case UpdateRowSource.None:
                case UpdateRowSource.OutputParameters:
                case UpdateRowSource.FirstReturnedRecord: 
                case UpdateRowSource.Both:
                    _updatedRowSource = value; 
                    break; 
                default:
                    throw ADP.InvalidUpdateRowSource(value); 
                }
            }
        }
 
        // Cancel is supposed to be multi-thread safe.
        // It doesn't make sense to verify the connection exists or that it is open during cancel 
        // because immediately after checkin the connection can be closed or removed via another thread. 
        //
        override public void Cancel() { 
            // According to [....]: Cancel is meant to cancel firehose cursors only,
            // not to cancel the execution of a statement.  Given that for Oracle, you
            // don't need to tell the server you don't want any more results, it would
            // seem that this is unnecessary, so I'm commenting it out until someone 
            // comes up with a reason for it.
            IntPtr hscp; 
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try {
#if UNUSED 
                int rc = TracedNativeMethods.OCIBreak(
                    ServiceContextHandle.GetHandle(),
                    ErrorHandle.Handle
                ); 

                if (0 != rc) { 
                    Connection.CheckError(ErrorHandle, rc); 
                }
#endif // 
            }
            finally {
                Bid.ScopeLeave(ref hscp);
            } 
        }
 
        public object Clone() { 
            OracleCommand clone = new OracleCommand(this);
            Bid.Trace(" %d#, clone=%d#\n", ObjectID, clone.ObjectID); 
            return clone;
        }

        new public OracleParameter CreateParameter() { 
            return new OracleParameter();
        } 
 
        override protected DbParameter CreateDbParameter() {
            return CreateParameter(); 
        }

        internal string Execute(OciStatementHandle statementHandle, CommandBehavior behavior, out ArrayList resultParameterOrdinals) {
            OciRowidDescriptor  temp1; 
            return Execute(statementHandle, behavior, false, out temp1, out resultParameterOrdinals);
        } 
 
        internal string Execute(OciStatementHandle statementHandle, CommandBehavior behavior, bool needRowid, out OciRowidDescriptor rowidDescriptor, out ArrayList resultParameterOrdinals) {
            //  common routine used to execute all statements 

            if (ConnectionIsClosed) {
                throw ADP.ClosedConnectionError();
            } 
            // throw if the connection is in a transaction but there is no
            // locally assigned transaction object 
            if ((null == _transaction) && (null != Connection.Transaction)) { 
                throw ADP.TransactionRequired();
            } 
            // if we have a transaction, check to ensure that the active
            // connection property matches the connection associated with
            // the transaction
            if ((null != _transaction) && (null != _transaction.Connection) && (Connection != _transaction.Connection)) { 
                throw ADP.TransactionConnectionMismatch();
            } 
            rowidDescriptor = null; 

            // if the connection has a command but it went out of scope, we need 
            // to roll it back.  We do this here instead of in the transaction
            // objects finalizer because it doesn't really matter when it gets
            // done, just as long as it is before the next command executes, and
            // it's easier to do it in the command object, than in the object 
            // that is being finalized.
            Connection.RollbackDeadTransaction(); 
 
            int                         rc = 0;
            NativeBuffer                parameterBuffer = null; 
            bool                        mustRelease = false;
            bool[]                      mustReleaseBindHandle = null;
            SafeHandle[]                handleToBind = null;
            short                       tempub2; 
            int                         iterations;
            OracleParameterBinding[]    parameterBinding = null; 
            string                      statementText = null; 

            resultParameterOrdinals = null; 

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
 
                // If we've already sent the statement to the server, then we don't need
                // to prepare it again... 
                if (_preparedStatementHandle != statementHandle) { 
                    statementText = StatementText;
 
                    rc = TracedNativeMethods.OCIStmtPrepare(
                                            statementHandle,
                                            ErrorHandle,
                                            statementText, 
                                            OCI.SYNTAX.OCI_NTV_SYNTAX,
                                            OCI.MODE.OCI_DEFAULT, 
                                            Connection 
                                            );
 
                    if (0 != rc) {
                        Connection.CheckError(ErrorHandle, rc);
                    }
                } 

                // Figure out what kind of statement we're dealing with and pick the 
                // appropriate iteration count. 
                statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_STMT_TYPE, out tempub2, ErrorHandle);
                _statementType = (OCI.STMT)tempub2; 

                if (OCI.STMT.OCI_STMT_SELECT != _statementType) {
                    iterations = 1;
                } 
                else {
                    iterations = 0; 
 
                    if (CommandBehavior.SingleRow != behavior) {
                        // We're doing our own "prefetching" to avoid double copies, so we 
                        // need to turn off Oracle's or it won't really help.
                        statementHandle.SetAttribute(OCI.ATTR.OCI_ATTR_PREFETCH_ROWS,   0,  ErrorHandle);
                        statementHandle.SetAttribute(OCI.ATTR.OCI_ATTR_PREFETCH_MEMORY, 0,  ErrorHandle);
                    } 
                }
 
                // Pick the execution mode we need to use 
                OCI.MODE        executeMode = OCI.MODE.OCI_DEFAULT;
 
                if (0 == iterations) {
                    if (IsBehavior(behavior, CommandBehavior.SchemaOnly)) {
                        // If we're only supposed to "describe" the data columns for the rowset, then
                        // use the describe only execute mode 
                        executeMode |= OCI.MODE.OCI_DESCRIBE_ONLY;
                    } 
                } 
                else {
                    if (TransactionState.AutoCommit == _connection.TransactionState) { 
                        // If we're in autocommit mode, then we have to tell Oracle to automatically
                        // commit the transaction it automatically created.
                        executeMode |= OCI.MODE.OCI_COMMIT_ON_SUCCESS;
                    } 
                    else if (TransactionState.GlobalStarted != _connection.TransactionState) {
                        // If we're not in "auto commit mode" then we can presume that Oracle 
                        // will automatically start a transaction, so we need to keep track 
                        // of that.
                        _connection.TransactionState = TransactionState.LocalStarted; 
                    }
                }

                    // Bind all the parameter values, unless we're just looking for schema info 
                if (0 == (executeMode & OCI.MODE.OCI_DESCRIBE_ONLY)) {
                    if (null != _parameterCollection && _parameterCollection.Count > 0) { 
                        int parameterBufferLength = 0; 
                        int length = _parameterCollection.Count;
 
                        mustReleaseBindHandle  = new bool[length];
                        handleToBind = new SafeHandle[length];
                        parameterBinding = new OracleParameterBinding[length];
 
                        for (int i = 0; i < length; ++i) {
                            parameterBinding[i] = new OracleParameterBinding(this, _parameterCollection[i]); 
                            parameterBinding[i].PrepareForBind( _connection, ref parameterBufferLength ); 

                            // If this is a ref cursor parameter that we're supposed to include 
                            // in the data reader, then add it to our list of those.
                            if (OracleType.Cursor == _parameterCollection[i].OracleType
                                || 0 < _parameterCollection[i].CommandSetResult) {
                                if (null == resultParameterOrdinals) { 
                                    resultParameterOrdinals = new ArrayList();
                                } 
                                resultParameterOrdinals.Add(i); 
                            }
                        } 

                        parameterBuffer = new NativeBuffer_ParameterBuffer(parameterBufferLength);

                        parameterBuffer.DangerousAddRef(ref mustRelease); 

                        for (int i = 0; i < length; ++i) { 
                            parameterBinding[i].Bind( statementHandle, parameterBuffer, _connection, ref mustReleaseBindHandle[i], ref handleToBind[i] ); 
                        }
                    } 
                }

                // OK, now go ahead and execute
                rc = TracedNativeMethods.OCIStmtExecute( 
                                        ServiceContextHandle,   // svchp
                                        statementHandle,        // stmtp 
                                        ErrorHandle,            // errhp 
                                        iterations,             // iters
                                        executeMode             // mode 
                                        );

                if (0 != rc)
                    Connection.CheckError(ErrorHandle, rc); 

                // and now, create the output parameter values 
                if (null != parameterBinding) { 
                    int length = parameterBinding.Length;
 
                    for (int i = 0; i < length; ++i) {
                        parameterBinding[i].PostExecute( parameterBuffer, _connection );
                        parameterBinding[i].Dispose();
                        parameterBinding[i] = null; 
                    }
                    parameterBinding = null; 
                } 

                if (needRowid && 0 == (executeMode & OCI.MODE.OCI_DESCRIBE_ONLY)) { 
                    switch (_statementType) {
                        case OCI.STMT.OCI_STMT_UPDATE:
                        case OCI.STMT.OCI_STMT_DELETE:
                        case OCI.STMT.OCI_STMT_INSERT: 
                            rowidDescriptor = statementHandle.GetRowid(EnvironmentHandle, ErrorHandle);
                            break; 
 
                        default:
                            rowidDescriptor = null; 
                            break;
                    }
                }
            } 
            finally {
                if (mustRelease) { 
                    parameterBuffer.DangerousRelease(); 
                }
 
                if (null != parameterBuffer) {
                    // We're done with these, get rid of them.
                    parameterBuffer.Dispose();
                    parameterBuffer = null; 
                }
 
                // and now, release/free the output parameter values 
                if (null != parameterBinding) {
                    int length = parameterBinding.Length; 

                    for (int i = 0; i < length; ++i) {
                        if (null != parameterBinding[i]) {
                            parameterBinding[i].Dispose(); 
                            parameterBinding[i] = null;
                        } 
                    } 
                    parameterBinding = null;
                } 

                if (null != mustReleaseBindHandle && null != handleToBind) {
                    int length = mustReleaseBindHandle.Length;
 
                    for (int i = 0; i < length; ++i) {
                        if (mustReleaseBindHandle[i]) { 
                            handleToBind[i].DangerousRelease(); 
                        }
                    } 
                }
            }
            return statementText;
        } 

        override protected DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { 
            return ExecuteReader(behavior); 
        }
 
        override public int ExecuteNonQuery() {
            OracleConnection.ExecutePermission.Demand();
            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try {
                OciRowidDescriptor  temp = null; 
                int         result = ExecuteNonQueryInternal(false, out temp); 
                OciHandle.SafeDispose(ref temp);    // shouldn't be necessary, but just in case...
                return result; 
            }
            finally {
                Bid.ScopeLeave(ref hscp);
            } 
        }
 
        private int ExecuteNonQueryInternal(bool needRowid, out OciRowidDescriptor rowidDescriptor) { 
            OciStatementHandle  statementHandle = null;
            int         rowcount = -1; 

            try {
                try {
                    ArrayList resultParameterOrdinals = new ArrayList(); 
                    statementHandle = GetStatementHandle();
                    Execute( statementHandle, CommandBehavior.Default, needRowid, out rowidDescriptor, out resultParameterOrdinals ); 
 
                    if (null != resultParameterOrdinals) {
                        rowcount = 0; 

                        foreach (int resultParameterOrdinal in resultParameterOrdinals) {
                            OracleParameter resultParameter = _parameterCollection[resultParameterOrdinal];
 
                            if (OracleType.Cursor != resultParameter.OracleType) {
                                Debug.Assert(0 < resultParameter.CommandSetResult, "non-ref cursor, non recordsaffected parameter?"); 
                                rowcount += (int)resultParameter.Value; 
                            }
                        } 
                    }
                    else {
                        if (OCI.STMT.OCI_STMT_SELECT != _statementType) {
                            statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_ROW_COUNT, out rowcount, ErrorHandle); 
                        }
                    } 
                } 
                finally {
                    if (null != statementHandle) 
                        ReleaseStatementHandle(statementHandle);
                }
            }
            catch { // Prevent exception filters from running in our space 
                throw;
            } 
 
            return rowcount;
        } 

        public int ExecuteOracleNonQuery(out OracleString rowid) {
            OracleConnection.ExecutePermission.Demand();
 
            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try { 
                OciRowidDescriptor  rowidDescriptor = null;
                int         result = ExecuteNonQueryInternal(true, out rowidDescriptor); 
                rowid = GetPersistedRowid( Connection, rowidDescriptor );
                OciHandle.SafeDispose(ref rowidDescriptor);
                return result;
            } 
            finally {
                Bid.ScopeLeave(ref hscp); 
            } 
        }
 
        public object ExecuteOracleScalar() {
            OracleConnection.ExecutePermission.Demand();

            IntPtr hscp; 
            Bid.ScopeEnter(out hscp, " %d#", ObjectID);
            try { 
                OciRowidDescriptor  temp = null; 
                object      result = ExecuteScalarInternal(false, false, out temp);
                OciHandle.SafeDispose(ref temp);    // shouldn't be necessary, but just in case... 
                return result;
            }
            finally {
                Bid.ScopeLeave(ref hscp); 
            }
        } 
 
        new public OracleDataReader ExecuteReader() {
            return ExecuteReader(CommandBehavior.Default); 
        }

        new public OracleDataReader ExecuteReader(CommandBehavior behavior) {
            OracleConnection.ExecutePermission.Demand(); 
            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#, behavior=%d{ds.CommandBehavior}\n", ObjectID, (int)behavior); 
            try { 
                OciStatementHandle  statementHandle = null;;
                OracleDataReader    reader = null; 
                ArrayList           resultParameterOrdinals = null;

                 try {
                    statementHandle = GetStatementHandle(); 

                    string statementText = Execute( statementHandle, behavior, out resultParameterOrdinals); 
 

                    // We're about to handle the prepared statement handle (if there was one) 
                    // to the data reader object; so we can't really hold on to it any longer.
                    if (statementHandle == _preparedStatementHandle) {
                        // Don't dispose the handle, we still need it!  just make our reference to it null.
                        _preparedStatementHandle = null; 
                        //
                    } 
 
                    if (null == resultParameterOrdinals)
                        reader = new OracleDataReader(this, statementHandle, statementText, behavior); 
                    else
                        reader = new OracleDataReader(this, resultParameterOrdinals, statementText, behavior);
                }
                finally { 
                    // if we didn't hand the statement to a reader, then release it
                    if (null != statementHandle && (null == reader || null != resultParameterOrdinals)) { 
                        ReleaseStatementHandle(statementHandle); 
                    }
                } 
                return reader;
            }
            finally {
                Bid.ScopeLeave(ref hscp); 
            }
        } 
 
        override public object ExecuteScalar() {
            OracleConnection.ExecutePermission.Demand(); 

            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID);
            try { 
                OciRowidDescriptor  temp;
                object result = ExecuteScalarInternal(true, false, out temp); 
                OciHandle.SafeDispose(ref temp);    // shouldn't be necessary, but just in case... 
                return result;
            } 
            finally {
                Bid.ScopeLeave(ref hscp);
            }
        } 

        private object ExecuteScalarInternal(bool needCLStype, bool needRowid, out OciRowidDescriptor rowidDescriptor) { 
            OciStatementHandle  statementHandle = null; 
            object      result = null;
            int         rc = 0; 

             try {
                statementHandle = GetStatementHandle();
 
                ArrayList temp = new ArrayList();
 
                Execute( statementHandle, CommandBehavior.Default, needRowid, out rowidDescriptor, out temp ); 

                if (OCI.STMT.OCI_STMT_SELECT == _statementType) { 
                    // We only care about one column; Oracle will handle the fact that the
                    // rest aren't define so don't bother allocating and gathering more column
                    // information than we need.
                    OracleColumn    column = new OracleColumn(statementHandle, 0, ErrorHandle, _connection); 
                    int             columnBufferLength = 0;
                    bool            mustRelease = false; 
                    bool            mustReleaseBindHandle = false; 
                    SafeHandle      bindHandle = null;
 
                    column.Describe(ref columnBufferLength, _connection, ErrorHandle);

                    NativeBuffer_RowBuffer columnBuffer = new NativeBuffer_RowBuffer(columnBufferLength, 1);
 
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try { 
                        columnBuffer.DangerousAddRef(ref mustRelease); 

                        column.Bind(statementHandle, columnBuffer, ErrorHandle, 0); 
                        column.Rebind(_connection, ref mustReleaseBindHandle, ref bindHandle);

                        // Now fetch one row into the buffer we've provided
                        rc = TracedNativeMethods.OCIStmtFetch( 
                                                statementHandle,            // stmtp
                                                ErrorHandle,                // errhp 
                                                1,                          // crows 
                                                OCI.FETCH.OCI_FETCH_NEXT,   // orientation
                                                OCI.MODE.OCI_DEFAULT        // mode 
                                                );
                        if ((int)OCI.RETURNCODE.OCI_NO_DATA != rc) {
                            if (0 != rc)
                                Connection.CheckError(ErrorHandle, rc); 

 
                            // Ask the column for the object value (we need to get the Value from 
                            // the object to ensure that we have a URT type object, not an Oracle
                            // type object) 
                            if (needCLStype)
                                result = column.GetValue(columnBuffer);
                            else
                                result = column.GetOracleValue(columnBuffer); 
                        }
                    } 
                    finally { 
                        if (mustReleaseBindHandle) {
                            bindHandle.DangerousRelease(); 
                        }
                        if (mustRelease) {
                            columnBuffer.DangerousRelease();
                        } 
                    }
                    GC.KeepAlive(column); 
                } 
            }
            finally { 
                if (null != statementHandle) {
                    ReleaseStatementHandle(statementHandle);
                }
            } 
            return result;
        } 
 
        static internal OracleString GetPersistedRowid(OracleConnection connection, OciRowidDescriptor rowidHandle) {
            //  This method returns an OracleString that holds the base64 string 
            //  representation of the rowid, which can be persisted past the lifetime
            //  of this process.

            OracleString result = OracleString.Null; 

            if (null == rowidHandle) 
                goto done;  // null if there isn't a rowid! 

            OciErrorHandle  errorHandle = connection.ErrorHandle; 
            NativeBuffer    rowidBuffer = connection.GetScratchBuffer(3970);
            bool            mustRelease = false;
            bool            mustReleaseRowidHandle = false;
            int             rc; 

            RuntimeHelpers.PrepareConstrainedRegions(); 
            try { 
                rowidBuffer.DangerousAddRef(ref mustRelease);
 
                if (OCI.ClientVersionAtLeastOracle9i) {
                    int bufferLength = rowidBuffer.Length;

                    rc = TracedNativeMethods.OCIRowidToChar(rowidHandle, 
                                                        rowidBuffer,
                                                        ref bufferLength, 
                                                        errorHandle 
                                                        );
                    if (0 != rc) { 
                        connection.CheckError(errorHandle, rc);
                    }
                    string stringValue = rowidBuffer.PtrToStringAnsi(0, bufferLength); // ROWID's always come back as Ansi...
 
                    result = new OracleString(stringValue);
                } 
                else { 
                    rowidHandle.DangerousAddRef(ref mustReleaseRowidHandle);
 
                    OciServiceContextHandle     serviceContextHandle = connection.ServiceContextHandle;

                    OciStatementHandle tempHandle = new OciStatementHandle(serviceContextHandle);
                    string          tempText = "begin :rowid := :rdesc; end;"; 
                    int             rdescIndicatorOffset= 0;
                    int             rdescLengthOffset   = 4; 
                    int             rdescValueOffset    = 8; 
                    int             rowidIndicatorOffset= 12;
                    int             rowidLengthOffset   = 16; 
                    int             rowidValueOffset    = 20;

                     try {
                        rc = TracedNativeMethods.OCIStmtPrepare( 
                                                tempHandle,
                                                errorHandle, 
                                                tempText, 
                                                OCI.SYNTAX.OCI_NTV_SYNTAX,
                                                OCI.MODE.OCI_DEFAULT, 
                                                connection
                                                );
                        if (0 != rc)
                            connection.CheckError(errorHandle, rc); 

                        IntPtr h1; 
                        IntPtr h2; 

                        // Need to clean these out, since we're re-using the scratch buffer, which 
                        // the prepare uses to convert the statement text.
                        rowidBuffer.WriteIntPtr(rdescValueOffset,       rowidHandle.DangerousGetHandle());
                        rowidBuffer.WriteInt32 (rdescIndicatorOffset,   0);
                        rowidBuffer.WriteInt32 (rdescLengthOffset,      4); 
                        rowidBuffer.WriteInt32 (rowidIndicatorOffset,   0);
                        rowidBuffer.WriteInt32 (rowidLengthOffset,      3950); 
 
                        rc = TracedNativeMethods.OCIBindByName(
                                        tempHandle, 
                                        out h1,
                                        errorHandle,
                                        "rowid",
                                        5, 
                                        rowidBuffer.DangerousGetDataPtr(rowidValueOffset),
                                        3950, 
                                        OCI.DATATYPE.VARCHAR2, 
                                        rowidBuffer.DangerousGetDataPtr(rowidIndicatorOffset),
                                        rowidBuffer.DangerousGetDataPtr(rowidLengthOffset), 
                                        OCI.MODE.OCI_DEFAULT
                                        );
                        if (0 != rc)
                            connection.CheckError(errorHandle, rc); 

                        rc = TracedNativeMethods.OCIBindByName( 
                                        tempHandle, 
                                        out h2,
                                        errorHandle, 
                                        "rdesc",
                                        5,
                                        rowidBuffer.DangerousGetDataPtr(rdescValueOffset),
                                        4, 
                                        OCI.DATATYPE.ROWID_DESC,
                                        rowidBuffer.DangerousGetDataPtr(rdescIndicatorOffset), 
                                        rowidBuffer.DangerousGetDataPtr(rdescLengthOffset), 
                                        OCI.MODE.OCI_DEFAULT
                                        ); 
                        if (0 != rc)
                            connection.CheckError(errorHandle, rc);

                        rc = TracedNativeMethods.OCIStmtExecute( 
                                                serviceContextHandle,   // svchp
                                                tempHandle,             // stmtp 
                                                errorHandle,            // errhp 
                                                1,                      // iters
                                                OCI.MODE.OCI_DEFAULT    // mode 
                                                );

                        if (0 != rc)
                            connection.CheckError(errorHandle, rc); 

                        if (rowidBuffer.ReadInt16(rowidIndicatorOffset) == (Int16)OCI.INDICATOR.ISNULL) 
                            goto done; 

                        result = new OracleString( 
                                                rowidBuffer,
                                                rowidValueOffset,
                                                rowidLengthOffset,
                                                MetaType.GetMetaTypeForType(OracleType.RowId), 
                                                connection,
                                                false,   // it's not unicode! 
                                                true 
                                                );
                        GC.KeepAlive(rowidHandle); 
                    }
                    finally {
                        OciHandle.SafeDispose(ref tempHandle);
                    } 
                }
            } 
            finally{ 
                if (mustReleaseRowidHandle) {
                    rowidHandle.DangerousRelease(); 
                }
                if (mustRelease) {
                    rowidBuffer.DangerousRelease();
                } 
            }
 
        done: 
            return result;
        } 

        private OciStatementHandle GetStatementHandle() {
            //  return either the prepared statement handle or a new one if nothign
            //  is prepared. 

            if (ConnectionIsClosed) { 
                throw ADP.ClosedConnectionError(); 
            }
            if (null != _preparedStatementHandle) { 
                // When we prepare the statement, we keep track of it's closed
                // count; if the connection has been closed since we prepared, then
                // the statement handle is no longer valid and must be tossed.
                if (_connection.CloseCount == _preparedAtCloseCount) { 
                    return _preparedStatementHandle;
                } 
                _preparedStatementHandle.Dispose(); 
                _preparedStatementHandle = null;
            } 
            return new OciStatementHandle(ServiceContextHandle);
        }

        static internal bool IsBehavior(CommandBehavior value, CommandBehavior condition) { 
            return (condition == (condition & value));
        } 
 
        override public void Prepare() {
            OracleConnection.ExecutePermission.Demand(); 

            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID);
            try { 

                if (ConnectionIsClosed) { 
                    throw ADP.ClosedConnectionError(); 
                }
                if (CommandType.Text == CommandType) { 
                    OciStatementHandle  preparedStatementHandle = GetStatementHandle();
                    int         preparedAtCloseCount = _connection.CloseCount;
                    string      statementText = StatementText;
 
                    int rc = TracedNativeMethods.OCIStmtPrepare(
                                                preparedStatementHandle, 
                                                ErrorHandle, 
                                                statementText,
                                                OCI.SYNTAX.OCI_NTV_SYNTAX, 
                                                OCI.MODE.OCI_DEFAULT,
                                                Connection
                                                );
 
                    if (0 != rc) {
                        Connection.CheckError(ErrorHandle, rc); 
                    } 
                    short   tempub2;
 
                    preparedStatementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_STMT_TYPE, out tempub2, ErrorHandle);
                    _statementType = (OCI.STMT)tempub2;

                    if (OCI.STMT.OCI_STMT_SELECT == _statementType) { 
                        rc = TracedNativeMethods.OCIStmtExecute(
                                            _connection.ServiceContextHandle, 
                                                                        // svchp 
                                            preparedStatementHandle,    // stmtp
                                            ErrorHandle,                // errhp 
                                            0,                          // iters
                                            OCI.MODE.OCI_DESCRIBE_ONLY  // mode
                                            );
 
                        if (0 != rc) {
                            Connection.CheckError(ErrorHandle, rc); 
                        } 
                    }
 
                    if (preparedStatementHandle != _preparedStatementHandle) {
                        OciHandle.SafeDispose(ref _preparedStatementHandle);
                    }
                    _preparedStatementHandle = preparedStatementHandle; 
                    _preparedAtCloseCount = preparedAtCloseCount;
 
                } 
                else if (null != _preparedStatementHandle) {
                    OciHandle.SafeDispose(ref _preparedStatementHandle); 
                }
            }
            finally {
                Bid.ScopeLeave(ref hscp); 
            }
        } 
 
        private void PropertyChanging() {
            //  common routine used to get rid of a statement handle; it disposes 
            //  of the handle unless it's the prepared handle

            if (null != _preparedStatementHandle) {
                _preparedStatementHandle.Dispose(); // the existing prepared statement is no longer valid 
                _preparedStatementHandle = null;
            } 
        } 

        private void ReleaseStatementHandle (OciStatementHandle statementHandle) { 
            //  common routine used to get rid of a statement handle; it disposes
            //  of the handle unless it's the prepared handle

            if (ConnectionState.Closed != Connection.State && _preparedStatementHandle != statementHandle) { 
                OciHandle.SafeDispose(ref statementHandle);
            } 
        } 
    };
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK