internal OleDbDataReader(OleDbConnection connection, OleDbCommand command, int depth, CommandBehavior commandBehavior)
 {
     this._connection = connection;
     this._command = command;
     this._commandBehavior = commandBehavior;
     if ((command != null) && (this._depth == 0))
     {
         this._parameterBindings = command.TakeBindingOwnerShip();
     }
     this._depth = depth;
 }
示例#2
0
        internal ColumnBinding(OleDbDataReader dataReader, int index, int indexForAccessor, int indexWithinAccessor,
                                OleDbParameter parameter, RowBinding rowbinding, Bindings bindings, tagDBBINDING binding, int offset,
                                bool ifIRowsetElseIRow) {

            Debug.Assert(null != rowbinding, "null rowbinding");
            Debug.Assert(null != bindings, "null bindings");
            Debug.Assert(ODB.SizeOf_tagDBBINDING <= offset, "invalid offset" + offset);

            _dataReader = dataReader;
            _rowbinding = rowbinding;
            _bindings = bindings;
            _index = index;
            _indexForAccessor = indexForAccessor;
            _indexWithinAccessor = indexWithinAccessor;

            if (null != parameter) {
                _parameter = parameter;
                _parameterChangeID = parameter.ChangeID;
            }
            _offsetStatus = binding.obStatus.ToInt32() + offset;
            _offsetLength = binding.obLength.ToInt32() + offset;
            _offsetValue  = binding.obValue.ToInt32() + offset;

            Debug.Assert(0 <= _offsetStatus, "negative _offsetStatus");
            Debug.Assert(0 <= _offsetLength, "negative _offsetLength");
            Debug.Assert(0 <= _offsetValue,  "negative _offsetValue");

            _ordinal = binding.iOrdinal.ToInt32();
            _maxLen = binding.cbMaxLen.ToInt32();
            _wType = binding.wType;
            _precision = binding.bPrecision;

            _ifIRowsetElseIRow = ifIRowsetElseIRow;

            SetSize(Bindings.ParamSize.ToInt32());
        }
 // may be called from either
 //      OleDbDataReader.Close/Dispose
 //      via OleDbCommand.Dispose or OleDbConnection.Close
 internal void CloseFromDataReader(Bindings bindings) {
     if (null != bindings) {
         if (canceling) {
             bindings.Dispose();
             Debug.Assert(_dbBindings == bindings, "bindings with two owners");
         }
         else {
             bindings.ApplyOutputParameters();
             ParameterBindings = bindings;
         }
     }
     _hasDataReader = false;
 }
        private void CreateAccessor() {
            Debug.Assert(System.Data.CommandType.Text == CommandType || System.Data.CommandType.StoredProcedure == CommandType, "CreateAccessor: incorrect CommandType");
            Debug.Assert(null == _dbBindings, "CreateAccessor: already has dbBindings");
            Debug.Assert(HasParameters(), "CreateAccessor: unexpected, no parameter collection");

            // do this first in-case the command doesn't support parameters
            UnsafeNativeMethods.ICommandWithParameters commandWithParameters = ICommandWithParameters();

            OleDbParameterCollection collection = _parameters;
            OleDbParameter[] parameters = new OleDbParameter[collection.Count];
            collection.CopyTo(parameters, 0);

            // _dbBindings is used as a switch during ExecuteCommand, so don't set it until everything okay
            Bindings bindings = new Bindings(parameters, collection.ChangeID);

            for (int i = 0; i < parameters.Length; ++i) {
                bindings.ForceRebind |= parameters[i].BindParameter(i, bindings);
            }

            bindings.AllocateForAccessor(null, 0, 0);

            ApplyParameterBindings(commandWithParameters, bindings.BindInfo);

            UnsafeNativeMethods.IAccessor iaccessor = IAccessor();
            OleDbHResult hr = bindings.CreateAccessor(iaccessor, ODB.DBACCESSOR_PARAMETERDATA);
            if (hr < 0) {
                ProcessResults(hr);
            }
            _dbBindings = bindings;
        }
 internal Bindings TakeBindingOwnerShip() {
     Bindings bindings = _dbBindings;
     _dbBindings = null;
     return bindings;
 }
        // ctor for an ICommandText, IMultipleResults, IRowset, IRow
        // ctor for an ADODB.Recordset, ADODB.Record or Hierarchial resultset
        internal OleDbDataReader(OleDbConnection connection, OleDbCommand command, int depth, CommandBehavior commandBehavior) {
            OleDbConnection.VerifyExecutePermission();
            
            _connection = connection;
            _command = command;
            _commandBehavior = commandBehavior;

            if ((null != command) && (0 == _depth)) {
                _parameterBindings = command.TakeBindingOwnerShip();
            }
            _depth = depth;
        }
        override public void Close() {
            IntPtr hscp;
            Bid.ScopeEnter(out hscp, "<oledb.OleDbDataReader.Close|API> %d#\n", ObjectID);
            try {
                OleDbConnection con = _connection;
                OleDbCommand cmd = _command;
                Bindings bindings = _parameterBindings;
                _connection = null;
                _command = null;
                _parameterBindings = null;

                _isClosed = true;

                DisposeOpenResults();
                _hasRows = false;

                if ((null != cmd) && cmd.canceling) { // MDAC 68964                
                    DisposeNativeMultipleResults();
                    
                    if (null != bindings) {
                        bindings.CloseFromConnection();
                        bindings = null;
                    }
                }
                else {
                    UnsafeNativeMethods.IMultipleResults multipleResults = _imultipleResults;
                    _imultipleResults = null;

                    if (null != multipleResults) {
                        // if we don't have a cmd, same as a cancel (don't call NextResults) which is ADODB behavior

                        try {
                            // tricky code path is an exception is thrown
                            // causing connection to do a ResetState and connection.Close
                            // resulting in OleDbCommand.CloseFromConnection
                            if ((null != cmd) && !cmd.canceling) { // MDAC 71435
                                IntPtr affected = IntPtr.Zero;
                                OleDbException nextResultsFailure = NextResults(multipleResults, null, cmd, out affected);
                                _recordsAffected = AddRecordsAffected(_recordsAffected, affected);
                                if (null != nextResultsFailure) {
                                    throw nextResultsFailure;
                                }
                            }
                        }
                        finally {
                            if (null != multipleResults) {
                                Marshal.ReleaseComObject(multipleResults);
                            }
                        }
                    }
                }

                if ((null != cmd) && (0 == _depth)) {
                    // return bindings back to the cmd after closure of root DataReader
                    cmd.CloseFromDataReader(bindings); // MDAC 52283
                }

                if (null != con) {
                    con.RemoveWeakReference(this);

                    // if the DataReader is Finalized it will not close the connection
                    if (IsCommandBehavior(CommandBehavior.CloseConnection)) {
                        con.Close();
                    }
                }

                // release unmanaged objects
                RowHandleBuffer rowHandleNativeBuffer = _rowHandleNativeBuffer;
                _rowHandleNativeBuffer = null;
                if (null != rowHandleNativeBuffer) {
                    rowHandleNativeBuffer.Dispose();
                }
            }
            finally {
                Bid.ScopeLeave(ref hscp);
            }
        }
        internal bool BindParameter(int index, Bindings bindings)
        {
            int          size;
            int          ptrSize;
            byte         precisionInternal;
            byte         scaleInternal;
            object       obj2     = this.Value;
            NativeDBType bindType = this.GetBindType(obj2);

            if (bindType.enumOleDbType == System.Data.OleDb.OleDbType.Empty)
            {
                throw ODB.UninitializedParameters(index, bindType.enumOleDbType);
            }
            this._coerceMetaType = bindType;
            obj2 = CoerceValue(obj2, bindType);
            this.CoercedValue = obj2;
            ParameterDirection direction = this.Direction;

            if (this.ShouldSerializePrecision())
            {
                precisionInternal = this.PrecisionInternal;
            }
            else
            {
                precisionInternal = this.ValuePrecision(obj2);
            }
            if (precisionInternal == 0)
            {
                precisionInternal = bindType.maxpre;
            }
            if (this.ShouldSerializeScale())
            {
                scaleInternal = this.ScaleInternal;
            }
            else
            {
                scaleInternal = this.ValueScale(obj2);
            }
            int wType = bindType.wType;

            if (bindType.islong)
            {
                ptrSize = ADP.PtrSize;
                if (this.ShouldSerializeSize())
                {
                    size = this.Size;
                }
                else if (0x81 == bindType.dbType)
                {
                    size = 0x7fffffff;
                }
                else if (130 == bindType.dbType)
                {
                    size = 0x3fffffff;
                }
                else
                {
                    size = 0x7fffffff;
                }
                wType |= 0x4000;
            }
            else if (bindType.IsVariableLength)
            {
                bool flag;
                if (!this.ShouldSerializeSize() && ADP.IsDirection(this, ParameterDirection.Output))
                {
                    throw ADP.UninitializedParameterSize(index, this._coerceMetaType.dataType);
                }
                if (this.ShouldSerializeSize())
                {
                    size = this.Size;
                    flag = false;
                }
                else
                {
                    size = this.ValueSize(obj2);
                    flag = true;
                }
                if (0 >= size)
                {
                    if (size != 0)
                    {
                        if (-1 != size)
                        {
                            throw ADP.InvalidSizeValue(size);
                        }
                        ptrSize = ADP.PtrSize;
                        wType  |= 0x4000;
                    }
                    else if (130 == wType)
                    {
                        ptrSize = 2;
                    }
                    else
                    {
                        ptrSize = 0;
                    }
                }
                else
                {
                    if (130 == bindType.wType)
                    {
                        ptrSize = (Math.Min(size, 0x3ffffffe) * 2) + 2;
                    }
                    else
                    {
                        ptrSize = size;
                    }
                    if (flag && (0x81 == bindType.dbType))
                    {
                        size = Math.Min(size, 0x3ffffffe) * 2;
                    }
                    if (0x2000 < ptrSize)
                    {
                        ptrSize = ADP.PtrSize;
                        wType  |= 0x4000;
                    }
                }
            }
            else
            {
                ptrSize = bindType.fixlen;
                size    = ptrSize;
            }
            bindings.CurrentIndex   = index;
            bindings.DataSourceType = bindType.dbString.DangerousGetHandle();
            bindings.Name           = ADP.PtrZero;
            bindings.ParamSize      = new IntPtr(size);
            bindings.Flags          = GetBindFlags(direction);
            bindings.Ordinal        = (IntPtr)(index + 1);
            bindings.Part           = bindType.dbPart;
            bindings.ParamIO        = GetBindDirection(direction);
            bindings.Precision      = precisionInternal;
            bindings.Scale          = scaleInternal;
            bindings.DbType         = wType;
            bindings.MaxLen         = ptrSize;
            if (Bid.AdvancedOn)
            {
                Bid.Trace("<oledb.struct.tagDBPARAMBINDINFO|INFO|ADV> index=%d, parameterName='%ls'\n", index, this.ParameterName);
                Bid.Trace("<oledb.struct.tagDBBINDING|INFO|ADV>\n");
            }
            return(this.IsParameterComputed());
        }
        // goal: call virtual property getters only once per parameter
        internal bool BindParameter(int index, Bindings bindings) {
            int changeID = _changeID;
            object value = Value;

            NativeDBType dbtype = GetBindType(value);
            if (OleDbType.Empty == dbtype.enumOleDbType) {
                throw ODB.UninitializedParameters(index, dbtype.enumOleDbType);
            }
            _coerceMetaType = dbtype;
            value = CoerceValue(value, dbtype);
            CoercedValue = value;

            ParameterDirection direction = Direction;

            byte precision;
            if (ShouldSerializePrecision()) {
                precision = PrecisionInternal;
            }
            else {
                precision = ValuePrecision(value);
            }
            if (0 == precision) {
                precision = dbtype.maxpre;
            }

            byte scale;
            if (ShouldSerializeScale()) {
                scale = ScaleInternal;
            }
            else {
                scale = ValueScale(value);
            }

            int wtype = dbtype.wType;
            int bytecount, size;

            if (dbtype.islong) { // long data (image, text, ntext)
                bytecount = ADP.PtrSize;
                if (ShouldSerializeSize()) {
                    size = Size;
                }
                else {
                    if (NativeDBType.STR == dbtype.dbType) {
                        size = Int32.MaxValue; // WebData 98940
                    }
                    else if (NativeDBType.WSTR == dbtype.dbType) {
                        size = Int32.MaxValue/2;
                    }
                    else {
                        size = Int32.MaxValue;
                    }
                }
                wtype |= NativeDBType.BYREF;
            }
            else if (dbtype.IsVariableLength) { // variable length data (varbinary, varchar, nvarchar)
                if (!ShouldSerializeSize() && ADP.IsDirection(this, ParameterDirection.Output)) {
                    throw ADP.UninitializedParameterSize(index, _coerceMetaType.dataType);
                }

                bool computedSize;
                if (ShouldSerializeSize()) {
                    size = Size;
                    computedSize = false;
                }
                else {
                    size = ValueSize(value);
                    computedSize = true;
                }
                if (0 < size) {
                    if (NativeDBType.WSTR == dbtype.wType) {
                        // maximum 0x3FFFFFFE characters, computed this way to avoid overflow exception
                        bytecount = Math.Min(size, 0x3FFFFFFE) * 2 + 2;
                    }
                    else {
                        Debug.Assert(NativeDBType.STR != dbtype.wType, "should have ANSI binding, describing is okay");
                        bytecount = size;
                    }

                    if (computedSize) {
                        if (NativeDBType.STR == dbtype.dbType) { // WebData 98140
                            // maximum 0x7ffffffe characters, computed this way to avoid overflow exception
                            size = Math.Min(size, 0x3FFFFFFE) * 2;
                        }
                    }

                    if (ODB.LargeDataSize < bytecount) {
                        bytecount = ADP.PtrSize;
                        wtype |= NativeDBType.BYREF;
                    }
                }
                else if (0 == size) {
                    if (NativeDBType.WSTR == wtype) { // allow space for null termination character
                        bytecount = 2;
                        // 0 == size, okay for (STR == dbType)
                    }
                    else {
                        Debug.Assert(NativeDBType.STR != dbtype.wType, "should have ANSI binding, describing is okay");
                        bytecount = 0;
                    }
                }
                else if (-1 == size) {
                    bytecount = ADP.PtrSize;
                    wtype |= NativeDBType.BYREF;
                }
                else {
                    throw ADP.InvalidSizeValue(size);
                }
            }
            else { // fixed length data
                bytecount = dbtype.fixlen;
                size = bytecount;
            }
            bindings.CurrentIndex = index;

            // tagDBPARAMBINDINFO info for SetParameterInfo
            bindings.DataSourceType = dbtype.dbString.DangerousGetHandle(); // NOTE: This is a constant and isn't exposed publicly, so there really isn't a potential for Handle Recycling.
            bindings.Name = ADP.PtrZero;
            bindings.ParamSize = new IntPtr(size);
            bindings.Flags = GetBindFlags(direction);
          //bindings.Precision    = precision;
          //bindings.Scale        = scale;

            // tagDBBINDING info for CreateAccessor
            bindings.Ordinal      = (IntPtr)(index+1);
            bindings.Part         = dbtype.dbPart;
            bindings.ParamIO      = GetBindDirection(direction);
            bindings.Precision    = precision;
            bindings.Scale        = scale;
            bindings.DbType       = wtype;
            bindings.MaxLen       = bytecount; // also increments databuffer size (uses DbType)
          //bindings.ValueOffset  = bindings.DataBufferSize; // set via MaxLen
          //bindings.LengthOffset = i * sizeof_int64;
          //bindings.StatusOffset = i * sizeof_int64 + sizeof_int32;
          //bindings.TypeInfoPtr  = 0;
          //bindings.ObjectPtr    = 0;
          //bindings.BindExtPtr   = 0;
          //bindings.MemOwner     = /*DBMEMOWNER_CLIENTOWNED*/0;
          //bindings.Flags        = 0;

          //bindings.ParameterChangeID = changeID; // bind until something changes
            Debug.Assert(_changeID == changeID, "parameter has unexpectedly changed");

            if (Bid.AdvancedOn) {
                Bid.Trace("<oledb.struct.tagDBPARAMBINDINFO|INFO|ADV> index=%d, parameterName='%ls'\n", index, ParameterName);//, bindings.BindInfo[index]);
                Bid.Trace("<oledb.struct.tagDBBINDING|INFO|ADV>\n");//, bindings.DBBinding[index]);
            }
            return IsParameterComputed();
        }
 internal ColumnBinding[] SetBindings(OleDbDataReader dataReader, Bindings bindings, int indexStart, int indexForAccessor, OleDbParameter[] parameters, tagDBBINDING[] dbbindings, bool ifIRowsetElseIRow)
 {
     bool success = false;
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
         base.DangerousAddRef(ref success);
         IntPtr handle = base.DangerousGetHandle();
         for (int j = 0; j < dbbindings.Length; j++)
         {
             IntPtr ptr = ADP.IntPtrOffset(handle, j * ODB.SizeOf_tagDBBINDING);
             Marshal.StructureToPtr(dbbindings[j], ptr, false);
         }
     }
     finally
     {
         if (success)
         {
             base.DangerousRelease();
         }
     }
     ColumnBinding[] bindingArray = new ColumnBinding[dbbindings.Length];
     for (int i = 0; i < bindingArray.Length; i++)
     {
         int index = indexStart + i;
         OleDbParameter parameter = (parameters != null) ? parameters[index] : null;
         bindingArray[i] = new ColumnBinding(dataReader, index, indexForAccessor, i, parameter, this, bindings, dbbindings[i], this._headerLength, ifIRowsetElseIRow);
     }
     return bindingArray;
 }
 private Bindings[] CreateBindingsFromMetaData(bool allowMultipleAccessor)
 {
     int count = 0;
     int num8 = 0;
     System.Data.OleDb.MetaData[] dataArray = this._metadata;
     int[] numArray = new int[dataArray.Length];
     int[] numArray2 = new int[dataArray.Length];
     if (allowMultipleAccessor)
     {
         if (this._irowset != null)
         {
             for (int k = 0; k < numArray.Length; k++)
             {
                 numArray[k] = count;
                 numArray2[k] = num8;
                 num8++;
             }
             if (0 < num8)
             {
                 count++;
             }
         }
         else if (this._irow != null)
         {
             for (int m = 0; m < numArray.Length; m++)
             {
                 numArray[m] = m;
                 numArray2[m] = 0;
             }
             count = dataArray.Length;
         }
     }
     else
     {
         for (int n = 0; n < numArray.Length; n++)
         {
             numArray[n] = 0;
             numArray2[n] = n;
         }
         count = 1;
     }
     Bindings[] bindingsArray = new Bindings[count];
     count = 0;
     for (int i = 0; i < dataArray.Length; i++)
     {
         Bindings bindings = bindingsArray[numArray[i]];
         if (bindings == null)
         {
             count = 0;
             for (int num12 = i; (num12 < dataArray.Length) && (count == numArray2[num12]); num12++)
             {
                 count++;
             }
             bindingsArray[numArray[i]] = bindings = new Bindings(this, null != this._irowset, count);
         }
         System.Data.OleDb.MetaData data = dataArray[i];
         int fixlen = data.type.fixlen;
         short wType = data.type.wType;
         if (-1 != data.size)
         {
             if (data.type.islong)
             {
                 fixlen = ADP.PtrSize;
                 wType = (short) (((ushort) wType) | 0x4000);
             }
             else if (-1 == fixlen)
             {
                 if (0x2000 < data.size)
                 {
                     fixlen = ADP.PtrSize;
                     wType = (short) (((ushort) wType) | 0x4000);
                 }
                 else if ((130 == wType) && (-1 != data.size))
                 {
                     fixlen = (data.size * 2) + 2;
                 }
                 else
                 {
                     fixlen = data.size;
                 }
             }
         }
         else if (fixlen < 0)
         {
             fixlen = ADP.PtrSize;
             wType = (short) (((ushort) wType) | 0x4000);
         }
         num8 = numArray2[i];
         bindings.CurrentIndex = num8;
         bindings.Ordinal = data.ordinal;
         bindings.Part = data.type.dbPart;
         bindings.Precision = data.precision;
         bindings.Scale = data.scale;
         bindings.DbType = wType;
         bindings.MaxLen = fixlen;
         if (Bid.AdvancedOn)
         {
             Bid.Trace("<oledb.struct.tagDBBINDING|INFO|ADV> index=%d, columnName='%ls'\n", i, data.columnName);
         }
     }
     int index = 0;
     int indexStart = 0;
     for (int j = 0; j < bindingsArray.Length; j++)
     {
         indexStart = bindingsArray[j].AllocateForAccessor(this, indexStart, j);
         ColumnBinding[] bindingArray = bindingsArray[j].ColumnBindings();
         for (int num10 = 0; num10 < bindingArray.Length; num10++)
         {
             dataArray[index].columnBinding = bindingArray[num10];
             dataArray[index].bindings = bindingsArray[j];
             index++;
         }
     }
     this._bindings = bindingsArray;
     return bindingsArray;
 }
 public override void Close()
 {
     IntPtr ptr2;
     Bid.ScopeEnter(out ptr2, "<oledb.OleDbDataReader.Close|API> %d#\n", this.ObjectID);
     try
     {
         OleDbConnection connection = this._connection;
         OleDbCommand command = this._command;
         Bindings bindings = this._parameterBindings;
         this._connection = null;
         this._command = null;
         this._parameterBindings = null;
         this._isClosed = true;
         this.DisposeOpenResults();
         this._hasRows = false;
         if ((command != null) && command.canceling)
         {
             this.DisposeNativeMultipleResults();
             if (bindings != null)
             {
                 bindings.CloseFromConnection();
                 bindings = null;
             }
         }
         else
         {
             UnsafeNativeMethods.IMultipleResults imultipleResults = this._imultipleResults;
             this._imultipleResults = null;
             if (imultipleResults != null)
             {
                 try
                 {
                     if ((command != null) && !command.canceling)
                     {
                         IntPtr zero = IntPtr.Zero;
                         OleDbException exception = NextResults(imultipleResults, null, command, out zero);
                         this._recordsAffected = AddRecordsAffected(this._recordsAffected, zero);
                         if (exception != null)
                         {
                             throw exception;
                         }
                     }
                 }
                 finally
                 {
                     if (imultipleResults != null)
                     {
                         Marshal.ReleaseComObject(imultipleResults);
                     }
                 }
             }
         }
         if ((command != null) && (this._depth == 0))
         {
             command.CloseFromDataReader(bindings);
         }
         if (connection != null)
         {
             connection.RemoveWeakReference(this);
             if (this.IsCommandBehavior(CommandBehavior.CloseConnection))
             {
                 connection.Close();
             }
         }
         RowHandleBuffer buffer = this._rowHandleNativeBuffer;
         this._rowHandleNativeBuffer = null;
         if (buffer != null)
         {
             buffer.Dispose();
         }
     }
     finally
     {
         Bid.ScopeLeave(ref ptr2);
     }
 }
 private void CreateAccessor()
 {
     System.Data.Common.UnsafeNativeMethods.ICommandWithParameters commandWithParameters = this.ICommandWithParameters();
     OleDbParameterCollection parameters = this._parameters;
     OleDbParameter[] array = new OleDbParameter[parameters.Count];
     parameters.CopyTo(array, 0);
     Bindings bindings = new Bindings(array, parameters.ChangeID);
     for (int i = 0; i < array.Length; i++)
     {
         bindings.ForceRebind |= array[i].BindParameter(i, bindings);
     }
     bindings.AllocateForAccessor(null, 0, 0);
     this.ApplyParameterBindings(commandWithParameters, bindings.BindInfo);
     System.Data.Common.UnsafeNativeMethods.IAccessor iaccessor = this.IAccessor();
     OleDbHResult hr = bindings.CreateAccessor(iaccessor, 4);
     if (hr < OleDbHResult.S_OK)
     {
         this.ProcessResults(hr);
     }
     this._dbBindings = bindings;
 }
 private void CloseInternalParameters()
 {
     Bindings bindings = this._dbBindings;
     this._dbBindings = null;
     if (bindings != null)
     {
         bindings.Dispose();
     }
 }
 internal void CloseFromDataReader(Bindings bindings)
 {
     if (bindings != null)
     {
         if (this.canceling)
         {
             bindings.Dispose();
         }
         else
         {
             bindings.ApplyOutputParameters();
             this.ParameterBindings = bindings;
         }
     }
     this._hasDataReader = false;
 }
 private void CloseInternalParameters() {
     Debug.Assert(null != _connection, "no connection, CloseInternalParameters");
     Bindings bindings = _dbBindings;
     _dbBindings = null;
     if (null != bindings) {
         bindings.Dispose();
     }
 }
示例#17
0
        internal ColumnBinding[] SetBindings(OleDbDataReader dataReader, Bindings bindings,
                                             int indexStart, int indexForAccessor,
                                             OleDbParameter[] parameters, tagDBBINDING[] dbbindings, bool ifIRowsetElseIRow) {
            Debug.Assert(null != bindings, "null bindings");
            Debug.Assert(dbbindings.Length == BindingCount(), "count mismatch");

            bool mustRelease = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                DangerousAddRef(ref mustRelease);

                IntPtr buffer = DangerousGetHandle();
                for(int i = 0; i < dbbindings.Length; ++i) {
                    IntPtr ptr = ADP.IntPtrOffset(buffer, (i * ODB.SizeOf_tagDBBINDING));
                    Marshal.StructureToPtr(dbbindings[i], ptr, false/*deleteold*/);
                }
            }
            finally {
                if (mustRelease) {
                    DangerousRelease();
                }
            }

            ColumnBinding[] columns = new ColumnBinding[dbbindings.Length];
            for(int indexWithinAccessor = 0; indexWithinAccessor < columns.Length; ++indexWithinAccessor) {
                int index = indexStart + indexWithinAccessor;
                OleDbParameter parameter = ((null != parameters) ? parameters[index] : null);
                columns[indexWithinAccessor] = new ColumnBinding(
                    dataReader, index, indexForAccessor, indexWithinAccessor,
                    parameter, this, bindings, dbbindings[indexWithinAccessor], _headerLength,
                    ifIRowsetElseIRow);
            }
            return columns;
        }
        private Bindings[] CreateBindingsFromMetaData(bool allowMultipleAccessor) {
            int bindingCount = 0;
            int currentBindingIndex = 0;

            MetaData[] metadata = _metadata;

            int[] indexToBinding = new int[metadata.Length];
            int[] indexWithinBinding = new int[metadata.Length];

            // walk through the schemaRows to determine the number of binding groups
            if (allowMultipleAccessor) {
                if (null != _irowset) {
                    for (int i = 0; i < indexToBinding.Length; ++i) {
                        indexToBinding[i] = bindingCount;
                        indexWithinBinding[i] = currentBindingIndex;
#if false
                        // @denote: single/multiple Accessors
                        if ((bindingCount < 2) && IsLong(metadata[i].flags)) {
                            bindingCount++;
                            currentBindingIndex = 0;
                        }
                        else {
                            currentBindingIndex++;
                        }
#elif false
                        // @devnote: one accessor per column option
                        bindingCount++;
                        currentBindingIndex = 0;
#else
                        // @devnote: one accessor only for IRowset
                        currentBindingIndex++;
#endif
                    }
                    if (0 < currentBindingIndex) { // when blob is not the last column
                        bindingCount++;
                    }
                }
                else if (null != _irow) {
                    for (int i = 0; i < indexToBinding.Length; ++i) {
                        indexToBinding[i] = i;
                        indexWithinBinding[i] = 0;
                    }
                    bindingCount = metadata.Length;
                }
            }
            else {
                for (int i = 0; i < indexToBinding.Length; ++i) {
                    indexToBinding[i] = 0;
                    indexWithinBinding[i] = i;
                }
                bindingCount = 1;
            }

            Bindings bindings;
            Bindings[] dbbindings = new Bindings[bindingCount];
            bindingCount = 0;

            // for every column, build tagDBBinding info
            for (int index = 0; index < metadata.Length; ++index) {
                Debug.Assert(indexToBinding[index] < dbbindings.Length, "bad indexToAccessor");
                bindings = dbbindings[indexToBinding[index]];
                if (null == bindings) {
                    bindingCount = 0;
                    for (int i = index; (i < metadata.Length) && (bindingCount == indexWithinBinding[i]); ++i) {
                        bindingCount++;
                    }
                    dbbindings[indexToBinding[index]] = bindings = new Bindings((OleDbDataReader)this, (null != _irowset), bindingCount);

                    // runningTotal is buffered to start values on 16-byte boundary
                    // the first columnCount * 8 bytes are for the length and status fields
                    //bindings.DataBufferSize = (bindingCount + (bindingCount % 2)) * sizeof_int64;
                }
                MetaData info = metadata[index];

                int maxLen = info.type.fixlen;
                short getType = info.type.wType;

                Debug.Assert(NativeDBType.STR != getType, "Should have bound as WSTR");
                Debug.Assert(!NativeDBType.HasHighBit(getType), "CreateAccessor - unexpected high bits on datatype");

                if (-1 != info.size) {
                    if (info.type.islong) {
                        maxLen = ADP.PtrSize;
                        getType = (short)((ushort) getType | (ushort) NativeDBType.BYREF);
                    }
                    else if (-1 == maxLen) {
                        // @devnote: not using provider owned memory for PDC, no one really supports it anyway.
                        /*if (((null != connection) && connection.PropertyGetProviderOwnedMemory())
                            || ((null != command) && command.Connection.PropertyGetProviderOwnedMemory())) {
                            bindings.MemOwner = DBMemOwner.ProviderOwned;

                            bindings.MaxLen = ADP.PtrSize;
                            bindings.DbType = (short) (getType | DbType.BYREF);
                        }
                        else*/

                        if (ODB.LargeDataSize < info.size) {
                            maxLen = ADP.PtrSize;
                            getType = (short)((ushort) getType | (ushort)NativeDBType.BYREF);
                        }
                        else if ((NativeDBType.WSTR == getType) && (-1 != info.size)) { // WebData 99298
                            maxLen = info.size * 2 + 2;
                        }
                        else {
                            maxLen = info.size;
                        }
                    }
                }
                else if (maxLen < 0) {
                    // if variable length and no defined size we require this to be byref at this time
                    /*if (((null != connection) && connection.PropertyGetProviderOwnedMemory())
                        || ((null != command) && command.Connection.PropertyGetProviderOwnedMemory())) {
                        bindings.MemOwner = DBMemOwner.ProviderOwned;
                    }*/
                    maxLen = ADP.PtrSize;
                    getType = (short)((ushort) getType | (ushort)NativeDBType.BYREF);
                }

                currentBindingIndex = indexWithinBinding[index];
                bindings.CurrentIndex = currentBindingIndex;

                bindings.Ordinal      = info.ordinal;
                bindings.Part         = info.type.dbPart;
                bindings.Precision    = (byte) info.precision;
                bindings.Scale        = (byte) info.scale;
                bindings.DbType       = (short) getType;
                bindings.MaxLen       = maxLen; // also increments databuffer size (uses DbType)

              //bindings.ValueOffset  = // set via MaxLen
              //bindings.LengthOffset = // set via MaxLen
              //bindings.StatusOffset = // set via MaxLen
              //bindings.TypeInfoPtr  = 0;
              //bindings.ObjectPtr    = 0;
              //bindings.BindExtPtr   = 0;
              //bindings.MemOwner     = /*DBMEMOWNER_CLIENTOWNED*/0;
              //bindings.ParamIO      = ODB.DBPARAMIO_NOTPARAM;
              //bindings.Flags        = 0;

                if (Bid.AdvancedOn) {
                    Bid.Trace("<oledb.struct.tagDBBINDING|INFO|ADV> index=%d, columnName='%ls'\n", index, info.columnName);//, bindings.bindings[index]);
                }
            }

            int count = 0, indexStart = 0;
            for (int i = 0; i < dbbindings.Length; ++i) {
                indexStart = dbbindings[i].AllocateForAccessor(this, indexStart, i);

                ColumnBinding[] columnBindings = dbbindings[i].ColumnBindings();
                for (int k = 0; k < columnBindings.Length; ++k) {
                    Debug.Assert(count == columnBindings[k].Index, "column binding mismatch");
                    metadata[count].columnBinding = columnBindings[k];
                    metadata[count].bindings = dbbindings[i];
                    count++;
                }
            }

            _bindings = dbbindings;
            return dbbindings;
        }
 internal bool BindParameter(int index, Bindings bindings)
 {
     int size;
     int ptrSize;
     byte precisionInternal;
     byte scaleInternal;
     object obj2 = this.Value;
     NativeDBType bindType = this.GetBindType(obj2);
     if (bindType.enumOleDbType == System.Data.OleDb.OleDbType.Empty)
     {
         throw ODB.UninitializedParameters(index, bindType.enumOleDbType);
     }
     this._coerceMetaType = bindType;
     obj2 = CoerceValue(obj2, bindType);
     this.CoercedValue = obj2;
     ParameterDirection direction = this.Direction;
     if (this.ShouldSerializePrecision())
     {
         precisionInternal = this.PrecisionInternal;
     }
     else
     {
         precisionInternal = this.ValuePrecision(obj2);
     }
     if (precisionInternal == 0)
     {
         precisionInternal = bindType.maxpre;
     }
     if (this.ShouldSerializeScale())
     {
         scaleInternal = this.ScaleInternal;
     }
     else
     {
         scaleInternal = this.ValueScale(obj2);
     }
     int wType = bindType.wType;
     if (bindType.islong)
     {
         ptrSize = ADP.PtrSize;
         if (this.ShouldSerializeSize())
         {
             size = this.Size;
         }
         else if (0x81 == bindType.dbType)
         {
             size = 0x7fffffff;
         }
         else if (130 == bindType.dbType)
         {
             size = 0x3fffffff;
         }
         else
         {
             size = 0x7fffffff;
         }
         wType |= 0x4000;
     }
     else if (bindType.IsVariableLength)
     {
         bool flag;
         if (!this.ShouldSerializeSize() && ADP.IsDirection(this, ParameterDirection.Output))
         {
             throw ADP.UninitializedParameterSize(index, this._coerceMetaType.dataType);
         }
         if (this.ShouldSerializeSize())
         {
             size = this.Size;
             flag = false;
         }
         else
         {
             size = this.ValueSize(obj2);
             flag = true;
         }
         if (0 >= size)
         {
             if (size != 0)
             {
                 if (-1 != size)
                 {
                     throw ADP.InvalidSizeValue(size);
                 }
                 ptrSize = ADP.PtrSize;
                 wType |= 0x4000;
             }
             else if (130 == wType)
             {
                 ptrSize = 2;
             }
             else
             {
                 ptrSize = 0;
             }
         }
         else
         {
             if (130 == bindType.wType)
             {
                 ptrSize = (Math.Min(size, 0x3ffffffe) * 2) + 2;
             }
             else
             {
                 ptrSize = size;
             }
             if (flag && (0x81 == bindType.dbType))
             {
                 size = Math.Min(size, 0x3ffffffe) * 2;
             }
             if (0x2000 < ptrSize)
             {
                 ptrSize = ADP.PtrSize;
                 wType |= 0x4000;
             }
         }
     }
     else
     {
         ptrSize = bindType.fixlen;
         size = ptrSize;
     }
     bindings.CurrentIndex = index;
     bindings.DataSourceType = bindType.dbString.DangerousGetHandle();
     bindings.Name = ADP.PtrZero;
     bindings.ParamSize = new IntPtr(size);
     bindings.Flags = GetBindFlags(direction);
     bindings.Ordinal = (IntPtr) (index + 1);
     bindings.Part = bindType.dbPart;
     bindings.ParamIO = GetBindDirection(direction);
     bindings.Precision = precisionInternal;
     bindings.Scale = scaleInternal;
     bindings.DbType = wType;
     bindings.MaxLen = ptrSize;
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<oledb.struct.tagDBPARAMBINDINFO|INFO|ADV> index=%d, parameterName='%ls'\n", index, this.ParameterName);
         Bid.Trace("<oledb.struct.tagDBBINDING|INFO|ADV>\n");
     }
     return this.IsParameterComputed();
 }
示例#20
0
        // goal: call virtual property getters only once per parameter
        internal bool BindParameter(int index, Bindings bindings)
        {
            int    changeID = _changeID;
            object?value    = Value;

            NativeDBType dbtype = GetBindType(value);

            if (OleDbType.Empty == dbtype.enumOleDbType)
            {
                throw ODB.UninitializedParameters(index, dbtype.enumOleDbType);
            }
            _coerceMetaType = dbtype;
            value           = CoerceValue(value, dbtype);
            CoercedValue    = value;

            ParameterDirection direction = Direction;

            byte precision;

            if (ShouldSerializePrecision())
            {
                precision = PrecisionInternal;
            }
            else
            {
                precision = ValuePrecision(value);
            }
            if (0 == precision)
            {
                precision = dbtype.maxpre;
            }

            byte scale;

            if (ShouldSerializeScale())
            {
                scale = ScaleInternal;
            }
            else
            {
                scale = ValueScale(value);
            }

            int wtype = dbtype.wType;
            int bytecount, size;

            if (dbtype.islong)
            { // long data (image, text, ntext)
                bytecount = ADP.PtrSize;
                if (ShouldSerializeSize())
                {
                    size = Size;
                }
                else
                {
                    if (NativeDBType.STR == dbtype.dbType)
                    {
                        size = int.MaxValue;
                    }
                    else if (NativeDBType.WSTR == dbtype.dbType)
                    {
                        size = int.MaxValue / 2;
                    }
                    else
                    {
                        size = int.MaxValue;
                    }
                }
                wtype |= NativeDBType.BYREF;
            }
            else if (dbtype.IsVariableLength)
            { // variable length data (varbinary, varchar, nvarchar)
                if (!ShouldSerializeSize() && ADP.IsDirection(this, ParameterDirection.Output))
                {
                    throw ADP.UninitializedParameterSize(index, _coerceMetaType.dataType !);
                }

                bool computedSize;
                if (ShouldSerializeSize())
                {
                    size         = Size;
                    computedSize = false;
                }
                else
                {
                    size         = ValueSize(value);
                    computedSize = true;
                }
                if (0 < size)
                {
                    if (NativeDBType.WSTR == dbtype.wType)
                    {
                        // maximum 0x3FFFFFFE characters, computed this way to avoid overflow exception
                        bytecount = Math.Min(size, 0x3FFFFFFE) * 2 + 2;
                    }
                    else
                    {
                        Debug.Assert(NativeDBType.STR != dbtype.wType, "should have ANSI binding, describing is okay");
                        bytecount = size;
                    }

                    if (computedSize)
                    {
                        if (NativeDBType.STR == dbtype.dbType)
                        {
                            // maximum 0x7ffffffe characters, computed this way to avoid overflow exception
                            size = Math.Min(size, 0x3FFFFFFE) * 2;
                        }
                    }

                    if (ODB.LargeDataSize < bytecount)
                    {
                        bytecount = ADP.PtrSize;
                        wtype    |= NativeDBType.BYREF;
                    }
                }
                else if (0 == size)
                {
                    if (NativeDBType.WSTR == wtype)
                    { // allow space for null termination character
                        bytecount = 2;
                        // 0 == size, okay for (STR == dbType)
                    }
                    else
                    {
                        Debug.Assert(NativeDBType.STR != dbtype.wType, "should have ANSI binding, describing is okay");
                        bytecount = 0;
                    }
                }
                else if (-1 == size)
                {
                    bytecount = ADP.PtrSize;
                    wtype    |= NativeDBType.BYREF;
                }
                else
                {
                    throw ADP.InvalidSizeValue(size);
                }
            }
            else
            { // fixed length data
                bytecount = dbtype.fixlen;
                size      = bytecount;
            }
            bindings.CurrentIndex = index;

            // tagDBPARAMBINDINFO info for SetParameterInfo
            bindings.DataSourceType = dbtype.dbString.DangerousGetHandle(); // NOTE: This is a constant and isn't exposed publicly, so there really isn't a potential for Handle Recycling.
            bindings.Name           = ADP.PtrZero;
            bindings.ParamSize      = new IntPtr(size);
            bindings.Flags          = GetBindFlags(direction);
            //bindings.Precision    = precision;
            //bindings.Scale        = scale;

            // tagDBBINDING info for CreateAccessor
            bindings.Ordinal   = (IntPtr)(index + 1);
            bindings.Part      = dbtype.dbPart;
            bindings.ParamIO   = GetBindDirection(direction);
            bindings.Precision = precision;
            bindings.Scale     = scale;
            bindings.DbType    = wtype;
            bindings.MaxLen    = bytecount; // also increments databuffer size (uses DbType)
                                            //bindings.ValueOffset  = bindings.DataBufferSize; // set via MaxLen
                                            //bindings.LengthOffset = i * sizeof_int64;
                                            //bindings.StatusOffset = i * sizeof_int64 + sizeof_int32;
                                            //bindings.TypeInfoPtr  = 0;
                                            //bindings.ObjectPtr    = 0;
                                            //bindings.BindExtPtr   = 0;
                                            //bindings.MemOwner     = /*DBMEMOWNER_CLIENTOWNED*/0;
                                            //bindings.Flags        = 0;

            //bindings.ParameterChangeID = changeID; // bind until something changes
            Debug.Assert(_changeID == changeID, "parameter has unexpectedly changed");

            return(IsParameterComputed());
        }