Пример #1
0
        private OdbcDataReader ExecuteReaderObject(CommandBehavior behavior, string method)   // MDAC 68324
        {
            if ((_cmdText == null) || (_cmdText == ""))
            {
                throw (ADP.CommandTextRequired(method));
            }

            OdbcDataReader localReader = null;

            try { // try-finally inside try-catch-throw
                try {
                    ValidateConnectionAndTransaction(method);
                    _canceling = false;

                    if (0 != (CommandBehavior.SingleRow & behavior))
                    {
                        // CommandBehavior.SingleRow implies CommandBehavior.SingleResult
                        behavior |= CommandBehavior.SingleResult;
                    }

                    IntPtr         keyinfostmt = IntPtr.Zero;
                    ODBC32.RETCODE retcode;

                    HandleRef stmt = GetStatementHandle();

                    if ((behavior & CommandBehavior.KeyInfo) == CommandBehavior.KeyInfo)
                    {
                        GetKeyInfoStatementHandle();
                    }

                    localReader = new OdbcDataReader(this, _cmdWrapper, behavior);

                    //Set command properties
                    //Not all drivers support timeout. So fail silently if error
                    if (supportsCommandTimeout)
                    {
                        retcode = (ODBC32.RETCODE)UnsafeNativeMethods.Odbc32.SQLSetStmtAttrW(
                            stmt,
                            (Int32)ODBC32.SQL_ATTR.QUERY_TIMEOUT,
                            (IntPtr)this.CommandTimeout,
                            (Int32)ODBC32.SQL_IS.UINTEGER
                            );
                        if (ODBC32.RETCODE.SUCCESS != retcode)
                        {
                            supportsCommandTimeout = false;
                        }
                    }
                    // todo: correct name is SQL_NB.ON/OFF for NOBROWSETABLE option (same values so not bug but should change name)
                    //
                    // todo: If we remember the state we can omit a lot of SQLSetStmtAttrW calls ...
                    //
                    if (Connection.IsV3Driver)
                    {
                        // Need to get the metadata information

                        //SQLServer actually requires browse info turned on ahead of time...
                        //Note: We ignore any failures, since this is SQLServer specific
                        //We won't specialcase for SQL Server but at least for non-V3 drivers
                        if (localReader.IsBehavior(CommandBehavior.KeyInfo))
                        {
                            retcode = (ODBC32.RETCODE)UnsafeNativeMethods.Odbc32.SQLSetStmtAttrW(
                                stmt,
                                (Int32)ODBC32.SQL_SOPT_SS.NOBROWSETABLE,
                                (IntPtr)ODBC32.SQL_HC.ON,
                                (Int32)ODBC32.SQL_IS.INTEGER
                                );
                            retcode = (ODBC32.RETCODE)UnsafeNativeMethods.Odbc32.SQLSetStmtAttrW(
                                stmt,
                                (Int32)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS,
                                (IntPtr)ODBC32.SQL_HC.ON,
                                (Int32)ODBC32.SQL_IS.INTEGER
                                );
                        }
                        else
                        {
                            retcode = (ODBC32.RETCODE)UnsafeNativeMethods.Odbc32.SQLSetStmtAttrW(
                                stmt,
                                (Int32)ODBC32.SQL_SOPT_SS.NOBROWSETABLE,
                                (IntPtr)ODBC32.SQL_HC.OFF,
                                (Int32)ODBC32.SQL_IS.INTEGER
                                );
                            retcode = (ODBC32.RETCODE)UnsafeNativeMethods.Odbc32.SQLSetStmtAttrW(
                                stmt,
                                (Int32)ODBC32.SQL_SOPT_SS.HIDDEN_COLUMNS,
                                (IntPtr)ODBC32.SQL_HC.OFF,
                                (Int32)ODBC32.SQL_IS.INTEGER
                                );
                        }
                    }

                    if (localReader.IsBehavior(CommandBehavior.KeyInfo) ||
                        localReader.IsBehavior(CommandBehavior.SchemaOnly))
                    {
    #if DEBUG
                        if (AdapterSwitches.OleDbTrace.TraceInfo)
                        {
                            ADP.DebugWriteLine("SQLPrepareW: " + CommandText);
                        }
    #endif
                        retcode = (ODBC32.RETCODE)UnsafeNativeMethods.Odbc32.SQLPrepareW(
                            stmt,
                            CommandText,
                            ODBC32.SQL_NTS
                            );

                        if (ODBC32.RETCODE.SUCCESS != retcode)
                        {
                            _connection.HandleError(stmt, ODBC32.SQL_HANDLE.STMT, retcode);
                        }
                    }

                    //Handle Parameters
                    //Note: We use the internal variable as to not instante a new object collection,
                    //for the the common case of using no parameters.
                    if ((null != _parameterCollection) && (0 < _parameterCollection.Count))
                    {
                        //Bind all the parameters to the statement
                        int count = _parameterCollection.Count;
                        _cmdWrapper.ReAllocParameterBuffers(count);

                        localReader.SetParameterBuffers(_cmdWrapper._parameterBuffer, _cmdWrapper._parameterintBuffer);

                        //Note: It's more efficent for this function to just tell the parameter which
                        //binding it is that for it to try and figure it out (IndexOf, etc).
                        for (int i = 0; i < count; ++i)
                        {
                            _parameterCollection[i].Bind(_cmdWrapper, this, (short)(i + 1), _cmdWrapper._parameterBuffer[i], _cmdWrapper._parameterintBuffer[i]);
                        }
                        _parameterCollection.CollectionIsBound = true;
                        _parameterCollection.BindingIsValid    = true;
                    }
                    if (!localReader.IsBehavior(CommandBehavior.SchemaOnly))
                    {
                        if (localReader.IsBehavior(CommandBehavior.KeyInfo) || _isPrepared)
                        {
                            //Already prepared, so use SQLExecute
                            retcode = (ODBC32.RETCODE)UnsafeNativeMethods.Odbc32.SQLExecute(stmt);
                            // Build metadata here
                            // localReader.GetSchemaTable();
                        }
                        else
                        {
    #if DEBUG
                            if (AdapterSwitches.OleDbTrace.TraceInfo)
                            {
                                ADP.DebugWriteLine("SQLExecDirectW: " + CommandText);
                            }
    #endif
                            //SQLExecDirect
                            retcode = (ODBC32.RETCODE)UnsafeNativeMethods.Odbc32.SQLExecDirectW(
                                stmt,                           // SQLHSTMT     StatementHandle
                                CommandText,                    // SQLCHAR *     StatementText
                                ODBC32.SQL_NTS                  // SQLINTEGER     TextLength
                                );
                        }

                        //Note: Execute will return NO_DATA for Update/Delete non-row returning queries
                        if ((ODBC32.RETCODE.SUCCESS != retcode) && (ODBC32.RETCODE.NO_DATA != retcode))
                        {
                            _connection.HandleError(stmt, ODBC32.SQL_HANDLE.STMT, retcode);
                        }
                    }
                    this.weakDataReaderReference = new WeakReference(localReader);
                    _connection.SetStateFetchingTrue();

                    // XXXCommand.Execute should position reader on first row returning result
                    // any exceptions in the initial non-row returning results should be thrown
                    // from from ExecuteXXX not the DataReader
                    if (!localReader.IsBehavior(CommandBehavior.SchemaOnly))
                    {
                        localReader.FirstResult();
                    }
                    cmdState = ConnectionState.Fetching;
                }
                finally {
                    if (ConnectionState.Fetching != cmdState)
                    {
                        if (null != localReader)
                        {
                            // clear bindings so we don't grab output parameters on a failed execute
                            int count = ((null != _parameterCollection) ? _parameterCollection.Count : 0);
                            for (int i = 0; i < count; ++i)
                            {
                                _parameterCollection[i].ClearBinding();
                            }
                            ((IDisposable)localReader).Dispose();
                        }
                        if (ConnectionState.Closed != cmdState)
                        {
                            cmdState = ConnectionState.Closed;
                            _connection.SetStateExecutingFalse();
                        }
                    }
                }
            }
            catch { // MDAC 81875
                throw;
            }
            GC.KeepAlive(localReader);
            GC.KeepAlive(this);
            return(localReader);
        }