1 //------------------------------------------------------------------------------
2 // <copyright file="DBBindings.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
9 namespace System.Data.OleDb {
12 using System.ComponentModel;
13 using System.Diagnostics;
15 using System.Data.Common;
16 using System.Globalization;
17 using System.Runtime.InteropServices;
18 using System.Security;
19 using System.Security.Permissions;
21 using System.Threading;
23 sealed internal class Bindings {
25 private readonly tagDBPARAMBINDINFO[] _bindInfo;
26 private readonly tagDBBINDING[] _dbbindings;
27 private readonly tagDBCOLUMNACCESS[] _dbcolumns;
29 private OleDbParameter[] _parameters;
30 private int _collectionChangeID;
32 private OleDbDataReader _dataReader;
33 private ColumnBinding[] _columnBindings;
34 private RowBinding _rowBinding;
38 private int _dataBufferSize;
39 private bool _ifIRowsetElseIRow;
40 private bool _forceRebind;
41 private bool _needToReset;
43 private Bindings(int count) {
46 _dbbindings = new tagDBBINDING[count];
47 for(int i = 0;i < _dbbindings.Length;++i) {
48 _dbbindings[i] = new tagDBBINDING();
50 _dbcolumns = new tagDBCOLUMNACCESS[count];
53 internal Bindings(OleDbParameter[] parameters, int collectionChangeID) : this(parameters.Length) {
54 _bindInfo = new tagDBPARAMBINDINFO[parameters.Length];
55 _parameters = parameters;
56 _collectionChangeID = collectionChangeID;
57 _ifIRowsetElseIRow = true;
60 internal Bindings(OleDbDataReader dataReader, bool ifIRowsetElseIRow, int count) : this(count) {
61 _dataReader = dataReader;
62 _ifIRowsetElseIRow = ifIRowsetElseIRow;
65 internal tagDBPARAMBINDINFO[] BindInfo {
66 get { return _bindInfo; }
68 internal tagDBCOLUMNACCESS[] DBColumnAccess {
69 get { return _dbcolumns; }
72 internal int CurrentIndex {
73 //get { return _index; }
75 Debug.Assert((0 <= value) && (value < _count), "bad binding index");
80 internal ColumnBinding[] ColumnBindings() {
81 Debug.Assert(null != _columnBindings, "null ColumnBindings");
82 return _columnBindings;
85 internal OleDbParameter[] Parameters() {
86 Debug.Assert(null != _parameters, "null Parameters");
90 internal RowBinding RowBinding() {
91 //Debug.Assert(null != _rowBinding, "null RowBinding");
95 internal bool ForceRebind {
96 get { return _forceRebind; }
97 set { _forceRebind = value; }
100 // tagDBPARAMBINDINFO member access
101 internal IntPtr DataSourceType {
102 //get { return _bindInfo[_index].pwszDataSourceType; }
104 _bindInfo[_index].pwszDataSourceType = value;
107 internal IntPtr Name {
108 //get { return _bindInfo[_index].pwszName; }
110 _bindInfo[_index].pwszName= value;
113 internal IntPtr ParamSize {
115 if (null != _bindInfo) {
116 return _bindInfo[_index].ulParamSize;
121 _bindInfo[_index].ulParamSize= value;
125 //get { return _bindInfo[_index].dwFlag; }
127 _bindInfo[_index].dwFlags= value;
131 // tagDBBINDING member access
133 internal IntPtr Ordinal { // iOrdinal
134 //get { return _dbbindings[_index].iOrdinal.ToInt32(); }
136 _dbbindings[_index].iOrdinal = value;
140 /*internal int ValueOffset { // obValue
141 get { return _dbbindings[_index].obValue.ToInt32(); }
143 internal int LengthOffset { // obLength
144 get { return _dbbindings[_index].obLength.ToInt32(); }
146 internal int StatusOffset { // obStatus
147 get { return _dbbindings[_index].obStatus.ToInt32(); }
150 internal int Part { // dwPart
152 //get { return _dbbindings[_index].dwPart; }
154 set { _dbbindings[_index].dwPart = value; }
156 internal int ParamIO { // eParamIO
158 //get { return _dbbindings[_index].eParamIO; }
160 set { _dbbindings[_index].eParamIO = value; }
162 internal int MaxLen { // cbMaxLen
163 //get { return (int) _dbbindings[_index].cbMaxLen; }
165 Debug.Assert(0 <= value, "invalid MaxLen");
167 _dbbindings[_index].obStatus = (IntPtr) (_dataBufferSize + 0);
168 _dbbindings[_index].obLength = (IntPtr) (_dataBufferSize + ADP.PtrSize);
169 _dbbindings[_index].obValue = (IntPtr) (_dataBufferSize + ADP.PtrSize + ADP.PtrSize);
170 _dataBufferSize += ADP.PtrSize + ADP.PtrSize;
173 case (NativeDBType.BSTR): // ADP.PtrSize
174 case (NativeDBType.HCHAPTER): // ADP.PtrSize
175 case (NativeDBType.PROPVARIANT): // sizeof(PROPVARIANT)
176 case (NativeDBType.VARIANT): // 16 or 24 (8 + ADP.PtrSize *2)
177 case (NativeDBType.BYREF | NativeDBType.BYTES): // ADP.PtrSize
178 case (NativeDBType.BYREF | NativeDBType.WSTR): // ADP.PtrSize
179 // allocate extra space to cache original value for disposal
180 _dataBufferSize += System.Data.OleDb.RowBinding.AlignDataSize(value*2);
184 _dataBufferSize += System.Data.OleDb.RowBinding.AlignDataSize(value);
188 _dbbindings[_index].cbMaxLen = (IntPtr)value;
189 _dbcolumns[_index].cbMaxLen = (IntPtr)value;
192 internal int DbType { // wType
193 get { return _dbbindings[_index].wType; }
195 _dbbindings[_index].wType = (short) value;
196 _dbcolumns[_index].wType = (short) value;
199 internal byte Precision { // bPrecision
201 //get { return _dbbindings[_index].bPrecision; }
205 if (null != _bindInfo) {
206 _bindInfo[_index].bPrecision = value;
208 _dbbindings[_index].bPrecision = value;
209 _dbcolumns[_index].bPrecision = value;
212 internal byte Scale { // bScale
214 //get { return _dbbindings[_index].bScale; }
217 if (null != _bindInfo) {
218 _bindInfo[_index].bScale = value;
220 _dbbindings[_index].bScale = value;
221 _dbcolumns[_index].bScale = value;
225 internal int AllocateForAccessor(OleDbDataReader dataReader, int indexStart, int indexForAccessor) {
226 Debug.Assert(null == _rowBinding, "row binding already allocated");
227 Debug.Assert(null == _columnBindings, "column bindings already allocated");
229 RowBinding rowBinding = System.Data.OleDb.RowBinding.CreateBuffer(_count, _dataBufferSize, _needToReset);
230 _rowBinding = rowBinding;
232 ColumnBinding[] columnBindings = rowBinding.SetBindings(dataReader, this, indexStart, indexForAccessor, _parameters, _dbbindings, _ifIRowsetElseIRow);
233 Debug.Assert(null != columnBindings, "null column bindings");
234 _columnBindings = columnBindings;
236 if (!_ifIRowsetElseIRow) {
237 Debug.Assert(columnBindings.Length == _dbcolumns.Length, "length mismatch");
238 for(int i = 0; i < columnBindings.Length; ++i) { // WebData 94427
239 _dbcolumns[i].pData = rowBinding.DangerousGetDataPtr(columnBindings[i].ValueOffset); // We are simply pointing at a location later in the buffer, so we're OK to not addref the buffer.
245 foreach(ColumnBinding binding in columnBindings) {
246 Debug.Assert(index < binding.Index, "invaild index");
247 index = binding.Index;
250 return (indexStart + columnBindings.Length);
254 internal void ApplyInputParameters() {
255 ColumnBinding[] columnBindings = this.ColumnBindings();
256 OleDbParameter[] parameters = this.Parameters();
258 RowBinding().StartDataBlock();
259 for(int i = 0; i < parameters.Length; ++i) {
260 if (ADP.IsDirection(parameters[i], ParameterDirection.Input)) {
261 columnBindings[i].SetOffset(parameters[i].Offset); // MDAC 80657
262 columnBindings[i].Value(parameters[i].GetCoercedValue());
265 // always set ouput only and return value parameter values to null when executing
266 parameters[i].Value = null;
268 //columnBindings[i].SetValueEmpty(); // webdata 115079
273 internal void ApplyOutputParameters() {
274 ColumnBinding[] columnBindings = this.ColumnBindings();
275 OleDbParameter[] parameters = this.Parameters();
277 for(int i = 0; i < parameters.Length; ++i) {
278 if (ADP.IsDirection(parameters[i], ParameterDirection.Output)) {
279 parameters[i].Value = columnBindings[i].Value();
285 internal bool AreParameterBindingsInvalid(OleDbParameterCollection collection) {
286 Debug.Assert(null != collection, "null parameter collection");
287 Debug.Assert(null != _parameters, "null parameters");
289 ColumnBinding[] columnBindings = this.ColumnBindings();
290 if (!ForceRebind && ((collection.ChangeID == _collectionChangeID) && (_parameters.Length == collection.Count))) {
291 for(int i = 0; i < columnBindings.Length; ++i) {
292 ColumnBinding binding = columnBindings[i];
294 Debug.Assert(null != binding, "null column binding");
295 Debug.Assert(binding.Parameter() == _parameters[i], "parameter mismatch");
296 if (binding.IsParameterBindingInvalid(collection[i])) {
297 //Debug.WriteLine("ParameterBindingsInvalid");
301 //Debug.WriteLine("ParameterBindingsValid");
302 return false; // collection and cached values are the same
304 //Debug.WriteLine("ParameterBindingsInvalid");
308 internal void CleanupBindings() {
309 RowBinding rowBinding = this.RowBinding();
310 if (null != rowBinding) {
311 rowBinding.ResetValues();
313 ColumnBinding[] columnBindings = this.ColumnBindings();
314 for(int i = 0; i < columnBindings.Length; ++i) {
315 ColumnBinding binding = columnBindings[i];
316 if (null != binding) {
317 binding.ResetValue();
323 internal void CloseFromConnection() {
324 if (null != _rowBinding) {
325 _rowBinding.CloseFromConnection();
330 internal OleDbHResult CreateAccessor(UnsafeNativeMethods.IAccessor iaccessor, int flags) {
331 Debug.Assert(null != _rowBinding, "no row binding");
332 Debug.Assert(null != _columnBindings, "no column bindings");
333 return _rowBinding.CreateAccessor(iaccessor, flags, _columnBindings);
336 public void Dispose() {
339 _columnBindings = null;
341 RowBinding rowBinding = _rowBinding;
343 if (null != rowBinding) {
344 rowBinding.Dispose();
348 internal void GuidKindName(Guid guid, int eKind, IntPtr propid) {
349 tagDBCOLUMNACCESS[] dbcolumns = DBColumnAccess;
350 dbcolumns[_index].columnid.uGuid = guid;
351 dbcolumns[_index].columnid.eKind = eKind;
352 dbcolumns[_index].columnid.ulPropid = propid;
355 internal void ParameterStatus(StringBuilder builder) {
356 ColumnBinding[] columnBindings = ColumnBindings();
357 for(int i = 0; i < columnBindings.Length; ++i) {
358 ODB.CommandParameterStatus(builder, i, columnBindings[i].StatusValue());