public void VerifyAddGivesDifferentPointers() { using (var handles = new GCHandleCollection()) { IntPtr p1 = handles.Add("foo"); IntPtr p2 = handles.Add("bar"); Assert.AreNotEqual(p1, p2); } }
public void VerifyAddingNullReturnsIntPtrZero() { using (var handles = new GCHandleCollection()) { IntPtr p = handles.Add(null); Assert.AreEqual(IntPtr.Zero, p); } }
public void VerifyAddGivesPointerToObject() { using (var handles = new GCHandleCollection()) { IntPtr p = handles.Add("expected"); string actual = Marshal.PtrToStringUni(p); Assert.AreEqual("expected", actual); } }
public void VerifyAddPinsObject() { var expected = new string('x', 5); var weakref = new WeakReference(expected); using (var handles = new GCHandleCollection()) { handles.Add(expected); expected = null; GC.Collect(); Assert.IsTrue(weakref.IsAlive); } }
/// <summary> /// Make native indexcreate structures from the managed ones. /// </summary> /// <param name="managedIndexCreates">Index create structures to convert.</param> /// <param name="handles">The handle collection used to pin the data.</param> /// <returns>Pinned native versions of the index creates.</returns> private static unsafe NATIVE_INDEXCREATE3[] GetNativeIndexCreate3s( IList <JET_INDEXCREATE> managedIndexCreates, ref GCHandleCollection handles) { NATIVE_INDEXCREATE3[] nativeIndices = null; if (managedIndexCreates != null && managedIndexCreates.Count > 0) { nativeIndices = new NATIVE_INDEXCREATE3[managedIndexCreates.Count]; for (int i = 0; i < managedIndexCreates.Count; ++i) { nativeIndices[i] = managedIndexCreates[i].GetNativeIndexcreate3(); if (null != managedIndexCreates[i].pidxUnicode) { NATIVE_UNICODEINDEX2 unicode = managedIndexCreates[i].pidxUnicode.GetNativeUnicodeIndex2(); unicode.szLocaleName = handles.Add(Util.ConvertToNullTerminatedUnicodeByteArray(managedIndexCreates[i].pidxUnicode.GetEffectiveLocaleName())); nativeIndices[i].pidxUnicode = (NATIVE_UNICODEINDEX2 *)handles.Add(unicode); nativeIndices[i].grbit |= (uint)VistaGrbits.IndexUnicode; } nativeIndices[i].szKey = handles.Add(Util.ConvertToNullTerminatedUnicodeByteArray(managedIndexCreates[i].szKey)); nativeIndices[i].szIndexName = handles.Add(Util.ConvertToNullTerminatedUnicodeByteArray(managedIndexCreates[i].szIndexName)); nativeIndices[i].rgconditionalcolumn = GetNativeConditionalColumns(managedIndexCreates[i].rgconditionalcolumn, true, ref handles); // Convert pSpaceHints. if (managedIndexCreates[i].pSpaceHints != null) { NATIVE_SPACEHINTS nativeSpaceHints = managedIndexCreates[i].pSpaceHints.GetNativeSpaceHints(); nativeIndices[i].pSpaceHints = handles.Add(nativeSpaceHints); } } } return(nativeIndices); }
public void GCHandleCollectionStress() { for (int i = 0; i < 1000; i++) { using (var handles = new GCHandleCollection()) { for (int j = 0; j < 100; j++) { IntPtr p = handles.Add(new byte[1]); Assert.AreNotEqual(IntPtr.Zero, p); } } } }
/// <summary> /// Creates a temporary table with a single index. A temporary table /// stores and retrieves records just like an ordinary table created /// using JetCreateTableColumnIndex. However, temporary tables are /// much faster than ordinary tables due to their volatile nature. /// They can also be used to very quickly sort and perform duplicate /// removal on record sets when accessed in a purely sequential manner. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="temporarytable"> /// Description of the temporary table to create on input. After a /// successful call, the structure contains the handle to the temporary /// table and column identifications. /// </param> /// <returns>An error code.</returns> public int JetOpenTemporaryTable2(JET_SESID sesid, JET_OPENTEMPORARYTABLE temporarytable) { TraceFunctionCall(); this.CheckSupportsWindows8Features("JetOpenTemporaryTable2"); CheckNotNull(temporarytable, "temporarytable"); NATIVE_OPENTEMPORARYTABLE2 nativetemporarytable = temporarytable.GetNativeOpenTemporaryTable2(); var nativecolumnids = new uint[nativetemporarytable.ccolumn]; NATIVE_COLUMNDEF[] nativecolumndefs = GetNativecolumndefs(temporarytable.prgcolumndef, temporarytable.ccolumn); unsafe { using (var gchandlecollection = new GCHandleCollection()) { // Pin memory nativetemporarytable.prgcolumndef = (NATIVE_COLUMNDEF *)gchandlecollection.Add(nativecolumndefs); nativetemporarytable.rgcolumnid = (uint *)gchandlecollection.Add(nativecolumnids); if (null != temporarytable.pidxunicode) { NATIVE_UNICODEINDEX2 unicode = temporarytable.pidxunicode.GetNativeUnicodeIndex2(); unicode.szLocaleName = gchandlecollection.Add(Util.ConvertToNullTerminatedUnicodeByteArray(temporarytable.pidxunicode.GetEffectiveLocaleName())); nativetemporarytable.pidxunicode = (NATIVE_UNICODEINDEX2 *)gchandlecollection.Add(unicode); } // Call the interop method int err = Err(NativeMethods.JetOpenTemporaryTable2(sesid.Value, ref nativetemporarytable)); // Convert the return values SetColumnids(temporarytable.prgcolumndef, temporarytable.prgcolumnid, nativecolumnids, temporarytable.ccolumn); temporarytable.tableid = new JET_TABLEID { Value = nativetemporarytable.tableid }; return(err); } } }
public void VerifyDisposeUnpinsObjects() { var expected = new string('x', 5); var weakref = new WeakReference(expected); using (var handles = new GCHandleCollection()) { handles.Add(expected); expected = null; // needed to allow GC to work } GC.Collect(); Assert.IsFalse(weakref.IsAlive); }
/// <summary> /// Creates a table, adds columns, and indices on that table. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="dbid">The database to which to add the new table.</param> /// <param name="tablecreate">Object describing the table to create.</param> /// <returns>An error if the call fails.</returns> private static int CreateTableColumnIndex4( JET_SESID sesid, JET_DBID dbid, JET_TABLECREATE tablecreate) { NATIVE_TABLECREATE4 nativeTableCreate = tablecreate.GetNativeTableCreate4(); unsafe { var handles = new GCHandleCollection(); try { // Convert/pin the column definitions. nativeTableCreate.rgcolumncreate = (NATIVE_COLUMNCREATE *)GetNativeColumnCreates(tablecreate.rgcolumncreate, true, ref handles); // Convert/pin the index definitions. NATIVE_INDEXCREATE3[] nativeIndexCreates = GetNativeIndexCreate3s(tablecreate.rgindexcreate, ref handles); nativeTableCreate.rgindexcreate = handles.Add(nativeIndexCreates); // Convert/pin the space hints. if (tablecreate.pSeqSpacehints != null) { NATIVE_SPACEHINTS nativeSpaceHints = tablecreate.pSeqSpacehints.GetNativeSpaceHints(); nativeTableCreate.pSeqSpacehints = (NATIVE_SPACEHINTS *)handles.Add(nativeSpaceHints); } if (tablecreate.pLVSpacehints != null) { NATIVE_SPACEHINTS nativeSpaceHints = tablecreate.pLVSpacehints.GetNativeSpaceHints(); nativeTableCreate.pLVSpacehints = (NATIVE_SPACEHINTS *)handles.Add(nativeSpaceHints); } int err = NativeMethods.JetCreateTableColumnIndex4W(sesid.Value, dbid.Value, ref nativeTableCreate); // Modified fields. tablecreate.tableid = new JET_TABLEID { Value = nativeTableCreate.tableid }; tablecreate.cCreated = checked ((int)nativeTableCreate.cCreated); if (tablecreate.rgcolumncreate != null) { for (int i = 0; i < tablecreate.rgcolumncreate.Length; ++i) { tablecreate.rgcolumncreate[i].SetFromNativeColumnCreate(ref nativeTableCreate.rgcolumncreate[i]); } } if (tablecreate.rgindexcreate != null) { for (int i = 0; i < tablecreate.rgindexcreate.Length; ++i) { tablecreate.rgindexcreate[i].SetFromNativeIndexCreate(ref nativeIndexCreates[i]); } } return(Err(err)); } finally { handles.Dispose(); } } }
/// <summary> /// Gets the NATIVE_indexcolumn structure that represents the object. /// </summary> /// <param name="handles">GC handle collection to add any pinned handles.</param> /// <returns>The NATIVE_indexcolumn structure.</returns> internal NATIVE_INDEX_COLUMN GetNativeIndexColumn(ref GCHandleCollection handles) { NATIVE_INDEX_COLUMN indexColumn = new NATIVE_INDEX_COLUMN(); indexColumn.columnid = this.columnid.Value; indexColumn.relop = (uint)this.relop; indexColumn.grbit = (uint)this.grbit; if (this.pvData != null) { indexColumn.pvData = handles.Add(this.pvData); indexColumn.cbData = (uint)this.pvData.Length; } return indexColumn; }
/// <summary> /// Creates a table, adds columns, and indices on that table. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="dbid">The database to which to add the new table.</param> /// <param name="tablecreate">Object describing the table to create.</param> /// <returns>An error if the call fails.</returns> private static int CreateTableColumnIndex4( JET_SESID sesid, JET_DBID dbid, JET_TABLECREATE tablecreate) { NATIVE_TABLECREATE4 nativeTableCreate = tablecreate.GetNativeTableCreate4(); unsafe { var handles = new GCHandleCollection(); try { // Convert/pin the column definitions. nativeTableCreate.rgcolumncreate = (NATIVE_COLUMNCREATE*)GetNativeColumnCreates(tablecreate.rgcolumncreate, true, ref handles); // Convert/pin the index definitions. NATIVE_INDEXCREATE3[] nativeIndexCreates = GetNativeIndexCreate3s(tablecreate.rgindexcreate, ref handles); nativeTableCreate.rgindexcreate = handles.Add(nativeIndexCreates); // Convert/pin the space hints. if (tablecreate.pSeqSpacehints != null) { NATIVE_SPACEHINTS nativeSpaceHints = tablecreate.pSeqSpacehints.GetNativeSpaceHints(); nativeTableCreate.pSeqSpacehints = (NATIVE_SPACEHINTS*)handles.Add(nativeSpaceHints); } if (tablecreate.pLVSpacehints != null) { NATIVE_SPACEHINTS nativeSpaceHints = tablecreate.pLVSpacehints.GetNativeSpaceHints(); nativeTableCreate.pLVSpacehints = (NATIVE_SPACEHINTS*)handles.Add(nativeSpaceHints); } int err = NativeMethods.JetCreateTableColumnIndex4W(sesid.Value, dbid.Value, ref nativeTableCreate); // Modified fields. tablecreate.tableid = new JET_TABLEID { Value = nativeTableCreate.tableid }; tablecreate.cCreated = checked((int)nativeTableCreate.cCreated); if (tablecreate.rgcolumncreate != null) { for (int i = 0; i < tablecreate.rgcolumncreate.Length; ++i) { tablecreate.rgcolumncreate[i].SetFromNativeColumnCreate(nativeTableCreate.rgcolumncreate[i]); } } if (tablecreate.rgindexcreate != null) { for (int i = 0; i < tablecreate.rgindexcreate.Length; ++i) { tablecreate.rgindexcreate[i].SetFromNativeIndexCreate(nativeIndexCreates[i]); } } return Err(err); } finally { handles.Dispose(); } } }
/// <summary> /// Make native indexcreate structures from the managed ones. /// </summary> /// <param name="managedIndexCreates">Index create structures to convert.</param> /// <param name="handles">The handle collection used to pin the data.</param> /// <returns>Pinned native versions of the index creates.</returns> private static unsafe NATIVE_INDEXCREATE3[] GetNativeIndexCreate3s( IList<JET_INDEXCREATE> managedIndexCreates, ref GCHandleCollection handles) { NATIVE_INDEXCREATE3[] nativeIndices = null; if (managedIndexCreates != null && managedIndexCreates.Count > 0) { nativeIndices = new NATIVE_INDEXCREATE3[managedIndexCreates.Count]; for (int i = 0; i < managedIndexCreates.Count; ++i) { nativeIndices[i] = managedIndexCreates[i].GetNativeIndexcreate3(); if (null != managedIndexCreates[i].pidxUnicode) { NATIVE_UNICODEINDEX2 unicode = managedIndexCreates[i].pidxUnicode.GetNativeUnicodeIndex2(); unicode.szLocaleName = handles.Add(Util.ConvertToNullTerminatedUnicodeByteArray(managedIndexCreates[i].pidxUnicode.GetEffectiveLocaleName())); nativeIndices[i].pidxUnicode = (NATIVE_UNICODEINDEX2*)handles.Add(unicode); nativeIndices[i].grbit |= (uint)VistaGrbits.IndexUnicode; } nativeIndices[i].szKey = handles.Add(Util.ConvertToNullTerminatedUnicodeByteArray(managedIndexCreates[i].szKey)); nativeIndices[i].szIndexName = handles.Add(Util.ConvertToNullTerminatedUnicodeByteArray(managedIndexCreates[i].szIndexName)); nativeIndices[i].rgconditionalcolumn = GetNativeConditionalColumns(managedIndexCreates[i].rgconditionalcolumn, true, ref handles); // Convert pSpaceHints. if (managedIndexCreates[i].pSpaceHints != null) { NATIVE_SPACEHINTS nativeSpaceHints = managedIndexCreates[i].pSpaceHints.GetNativeSpaceHints(); nativeIndices[i].pSpaceHints = handles.Add(nativeSpaceHints); } } } return nativeIndices; }
/// <summary> /// If the records with the specified key ranges are not in the /// buffer cache then start asynchronous reads to bring the records /// into the database buffer cache. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to issue the prereads against.</param> /// <param name="keysStart">The start of key ranges to preread.</param> /// <param name="keyStartLengths">The lengths of the start keys to preread.</param> /// <param name="keysEnd">The end of key rangess to preread.</param> /// <param name="keyEndLengths">The lengths of the end keys to preread.</param> /// <param name="rangeIndex">The index of the first key range in the array to read.</param> /// <param name="rangeCount">The maximum number of key ranges to preread.</param> /// <param name="rangesPreread">Returns the number of keys actually preread.</param> /// <param name="columnsPreread">List of column ids for long value columns to preread.</param> /// <param name="grbit">Preread options. Used to specify the direction of the preread.</param> /// <returns>An error or warning.</returns> public int JetPrereadKeyRanges( JET_SESID sesid, JET_TABLEID tableid, byte[][] keysStart, int[] keyStartLengths, byte[][] keysEnd, int[] keyEndLengths, int rangeIndex, int rangeCount, out int rangesPreread, JET_COLUMNID[] columnsPreread, PrereadIndexRangesGrbit grbit) { TraceFunctionCall("JetPrereadKeyRanges"); this.CheckSupportsWindows8Features("JetPrereadKeyRanges"); CheckDataSize(keysStart, rangeIndex, "rangeIndex", rangeCount, "rangeCount"); CheckDataSize(keyStartLengths, rangeIndex, "rangeIndex", rangeCount, "rangeCount"); CheckNotNull(keysStart, "keysStart"); if (keysEnd != null) { CheckNotNull(keyEndLengths, "keyEndLengths"); CheckDataSize(keysEnd, rangeIndex, "rangeIndex", rangeCount, "rangeCount"); } if (keyEndLengths != null) { CheckNotNull(keysEnd, "keysEnd"); CheckDataSize(keyEndLengths, rangeIndex, "rangeIndex", rangeCount, "rangeCount"); } grbit = grbit | PrereadIndexRangesGrbit.NormalizedKey; using (var handles = new GCHandleCollection()) { NATIVE_INDEX_COLUMN[] startColumn; NATIVE_INDEX_COLUMN[] endColumn; NATIVE_INDEX_RANGE[] ranges = new NATIVE_INDEX_RANGE[rangeCount]; for (int i = 0; i < rangeCount; i++) { startColumn = new NATIVE_INDEX_COLUMN[1]; startColumn[0].pvData = handles.Add(keysStart[i + rangeIndex]); startColumn[0].cbData = (uint)keyStartLengths[i + rangeIndex]; ranges[i].rgStartColumns = handles.Add(startColumn); ranges[i].cStartColumns = 1; if (keysEnd != null) { endColumn = new NATIVE_INDEX_COLUMN[1]; endColumn[0].pvData = handles.Add(keysEnd[i + rangeIndex]); endColumn[0].cbData = (uint)keyEndLengths[i + rangeIndex]; ranges[i].rgEndColumns = handles.Add(endColumn); ranges[i].cEndColumns = 1; } } if (columnsPreread != null) { var nativecolumnids = new uint[columnsPreread.Length]; for (int i = 0; i < columnsPreread.Length; i++) { nativecolumnids[i] = (uint)columnsPreread[i].Value; } return Err(NativeMethods.JetPrereadIndexRanges(sesid.Value, tableid.Value, ranges, (uint)rangeCount, out rangesPreread, nativecolumnids, (uint)columnsPreread.Length, checked((uint)grbit))); } else { return Err(NativeMethods.JetPrereadIndexRanges(sesid.Value, tableid.Value, ranges, (uint)rangeCount, out rangesPreread, null, (uint)0, checked((uint)grbit))); } } }
/// <summary> /// Creates a temporary table with a single index. A temporary table /// stores and retrieves records just like an ordinary table created /// using JetCreateTableColumnIndex. However, temporary tables are /// much faster than ordinary tables due to their volatile nature. /// They can also be used to very quickly sort and perform duplicate /// removal on record sets when accessed in a purely sequential manner. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="temporarytable"> /// Description of the temporary table to create on input. After a /// successful call, the structure contains the handle to the temporary /// table and column identifications. /// </param> /// <returns>An error code.</returns> public int JetOpenTemporaryTable2(JET_SESID sesid, JET_OPENTEMPORARYTABLE temporarytable) { TraceFunctionCall("JetOpenTemporaryTable2"); this.CheckSupportsWindows8Features("JetOpenTemporaryTable2"); CheckNotNull(temporarytable, "temporarytable"); NATIVE_OPENTEMPORARYTABLE2 nativetemporarytable = temporarytable.GetNativeOpenTemporaryTable2(); var nativecolumnids = new uint[nativetemporarytable.ccolumn]; NATIVE_COLUMNDEF[] nativecolumndefs = GetNativecolumndefs(temporarytable.prgcolumndef, temporarytable.ccolumn); unsafe { using (var gchandlecollection = new GCHandleCollection()) { // Pin memory nativetemporarytable.prgcolumndef = (NATIVE_COLUMNDEF*)gchandlecollection.Add(nativecolumndefs); nativetemporarytable.rgcolumnid = (uint*)gchandlecollection.Add(nativecolumnids); if (null != temporarytable.pidxunicode) { NATIVE_UNICODEINDEX2 unicode = temporarytable.pidxunicode.GetNativeUnicodeIndex2(); unicode.szLocaleName = gchandlecollection.Add(Util.ConvertToNullTerminatedUnicodeByteArray(temporarytable.pidxunicode.GetEffectiveLocaleName())); nativetemporarytable.pidxunicode = (NATIVE_UNICODEINDEX2*)gchandlecollection.Add(unicode); } // Call the interop method int err = Err(NativeMethods.JetOpenTemporaryTable2(sesid.Value, ref nativetemporarytable)); // Convert the return values SetColumnids(temporarytable.prgcolumndef, temporarytable.prgcolumnid, nativecolumnids, temporarytable.ccolumn); temporarytable.tableid = new JET_TABLEID { Value = nativetemporarytable.tableid }; return err; } } }
public static JET_wrn JetSetColumns(JET_SESID sesid, JET_TABLEID tableid, JET_SETCOLUMN[] setcolumns, int numColumns) { if (null == setcolumns) { throw new ArgumentNullException("setcolumns"); } if (numColumns < 0 || numColumns > setcolumns.Length) { throw new ArgumentOutOfRangeException("numColumns", numColumns, "cannot be negative or greater than setcolumns.Length"); } using (var gchandles = new GCHandleCollection()) { unsafe { NATIVE_SETCOLUMN* nativeSetColumns = stackalloc NATIVE_SETCOLUMN[numColumns]; // For performance, copy small amounts of data into a local buffer instead // of pinning the data. const int BufferSize = 128; byte* buffer = stackalloc byte[BufferSize]; int bufferRemaining = BufferSize; for (int i = 0; i < numColumns; ++i) { setcolumns[i].CheckDataSize(); nativeSetColumns[i] = setcolumns[i].GetNativeSetcolumn(); if (null == setcolumns[i].pvData) { nativeSetColumns[i].pvData = IntPtr.Zero; } else if (bufferRemaining >= setcolumns[i].cbData) { nativeSetColumns[i].pvData = new IntPtr(buffer); Marshal.Copy(setcolumns[i].pvData, setcolumns[i].ibData, nativeSetColumns[i].pvData, setcolumns[i].cbData); buffer += setcolumns[i].cbData; bufferRemaining -= setcolumns[i].cbData; Debug.Assert(bufferRemaining >= 0, "Buffer remaining is negative"); } else { byte* pinnedBuffer = (byte*)gchandles.Add(setcolumns[i].pvData).ToPointer(); nativeSetColumns[i].pvData = new IntPtr(pinnedBuffer + setcolumns[i].ibData); } } int err = Impl.JetSetColumns(sesid, tableid, nativeSetColumns, numColumns); for (int i = 0; i < numColumns; ++i) { setcolumns[i].err = (JET_wrn)nativeSetColumns[i].err; } return Api.Check(err); } } }
/// <summary> /// If the records with the specified key ranges are not in the /// buffer cache then start asynchronous reads to bring the records /// into the database buffer cache. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to issue the prereads against.</param> /// <param name="keysStart">The start of key ranges to preread.</param> /// <param name="keyStartLengths">The lengths of the start keys to preread.</param> /// <param name="keysEnd">The end of key rangess to preread.</param> /// <param name="keyEndLengths">The lengths of the end keys to preread.</param> /// <param name="rangeIndex">The index of the first key range in the array to read.</param> /// <param name="rangeCount">The maximum number of key ranges to preread.</param> /// <param name="rangesPreread">Returns the number of keys actually preread.</param> /// <param name="columnsPreread">List of column ids for long value columns to preread.</param> /// <param name="grbit">Preread options. Used to specify the direction of the preread.</param> /// <returns>An error or warning.</returns> public int JetPrereadKeyRanges( JET_SESID sesid, JET_TABLEID tableid, byte[][] keysStart, int[] keyStartLengths, byte[][] keysEnd, int[] keyEndLengths, int rangeIndex, int rangeCount, out int rangesPreread, JET_COLUMNID[] columnsPreread, PrereadIndexRangesGrbit grbit) { TraceFunctionCall(); this.CheckSupportsWindows8Features("JetPrereadKeyRanges"); CheckDataSize(keysStart, rangeIndex, "rangeIndex", rangeCount, "rangeCount"); CheckDataSize(keyStartLengths, rangeIndex, "rangeIndex", rangeCount, "rangeCount"); CheckNotNull(keysStart, "keysStart"); if (keysEnd != null) { CheckNotNull(keyEndLengths, "keyEndLengths"); CheckDataSize(keysEnd, rangeIndex, "rangeIndex", rangeCount, "rangeCount"); } if (keyEndLengths != null) { CheckNotNull(keysEnd, "keysEnd"); CheckDataSize(keyEndLengths, rangeIndex, "rangeIndex", rangeCount, "rangeCount"); } grbit = grbit | PrereadIndexRangesGrbit.NormalizedKey; using (var handles = new GCHandleCollection()) { NATIVE_INDEX_COLUMN[] startColumn; NATIVE_INDEX_COLUMN[] endColumn; NATIVE_INDEX_RANGE[] ranges = new NATIVE_INDEX_RANGE[rangeCount]; for (int i = 0; i < rangeCount; i++) { startColumn = new NATIVE_INDEX_COLUMN[1]; startColumn[0].pvData = handles.Add(keysStart[i + rangeIndex]); startColumn[0].cbData = (uint)keyStartLengths[i + rangeIndex]; ranges[i].rgStartColumns = handles.Add(startColumn); ranges[i].cStartColumns = 1; if (keysEnd != null) { endColumn = new NATIVE_INDEX_COLUMN[1]; endColumn[0].pvData = handles.Add(keysEnd[i + rangeIndex]); endColumn[0].cbData = (uint)keyEndLengths[i + rangeIndex]; ranges[i].rgEndColumns = handles.Add(endColumn); ranges[i].cEndColumns = 1; } } if (columnsPreread != null) { var nativecolumnids = new uint[columnsPreread.Length]; for (int i = 0; i < columnsPreread.Length; i++) { nativecolumnids[i] = (uint)columnsPreread[i].Value; } return(Err(NativeMethods.JetPrereadIndexRanges(sesid.Value, tableid.Value, ranges, (uint)rangeCount, out rangesPreread, nativecolumnids, (uint)columnsPreread.Length, checked ((uint)grbit)))); } else { return(Err(NativeMethods.JetPrereadIndexRanges(sesid.Value, tableid.Value, ranges, (uint)rangeCount, out rangesPreread, null, (uint)0, checked ((uint)grbit)))); } } }
/// <summary> /// Gets the NATIVE_indexcolumn structure that represents the object. /// </summary> /// <param name="handles">GC handle collection to add any pinned handles.</param> /// <returns>The NATIVE_indexcolumn structure.</returns> internal NATIVE_INDEX_RANGE GetNativeIndexRange(ref GCHandleCollection handles) { NATIVE_INDEX_RANGE indexRange = new NATIVE_INDEX_RANGE(); NATIVE_INDEX_COLUMN[] nativeColumns; if (this.startColumns != null) { nativeColumns = new NATIVE_INDEX_COLUMN[this.startColumns.Length]; for (int i = 0; i < this.startColumns.Length; i++) { nativeColumns[i] = this.startColumns[i].GetNativeIndexColumn(ref handles); } indexRange.rgStartColumns = handles.Add(nativeColumns); indexRange.cStartColumns = (uint)this.startColumns.Length; } if (this.endColumns != null) { nativeColumns = new NATIVE_INDEX_COLUMN[this.endColumns.Length]; for (int i = 0; i < this.endColumns.Length; i++) { nativeColumns[i] = this.endColumns[i].GetNativeIndexColumn(ref handles); } indexRange.rgEndColumns = handles.Add(nativeColumns); indexRange.cEndColumns = (uint)this.endColumns.Length; } return indexRange; }