static private Check ( int err ) : JET_wrn | ||
err | int | The error code to check. |
return | JET_wrn |
/// <summary> /// Starts and stops database defragmentation tasks that improves data /// organization within a database. /// </summary> /// <param name="sesid">The session to use for the call.</param> /// <param name="dbid">The database to be defragmented.</param> /// <param name="tableName"> /// Under some options defragmentation is performed for the entire database described by the given /// database ID, and other options (such as <see cref="Windows7.Windows7Grbits.DefragmentBTree"/>) require /// the name of the table to defragment. /// </param> /// <param name="grbit">Defragmentation options.</param> /// <returns>A warning code.</returns> /// <seealso cref="Api.JetDefragment"/> public static JET_wrn Defragment( JET_SESID sesid, JET_DBID dbid, string tableName, DefragGrbit grbit) { return(Api.Check(Impl.Defragment(sesid, dbid, tableName, grbit))); }
/// <summary> /// Removes an index range created with <see cref="JetSetIndexRange"/> or /// <see cref="TrySetIndexRange"/>. If no index range is present this /// method does nothing. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to remove the index range on.</param> public static void ResetIndexRange(JET_SESID sesid, JET_TABLEID tableid) { var err = (JET_err)Impl.JetSetIndexRange(sesid, tableid, SetIndexRangeGrbit.RangeRemove); if (err >= JET_err.Success || JET_err.InvalidOperation == err) { return; } Api.Check((int)err); throw new NotImplementedException("Unreachable code"); }
/// <summary> /// Temporarily limits the set of index entries that the cursor can walk using /// JetMove to those starting from the current index entry and ending at the index /// entry that matches the search criteria specified by the search key in that cursor /// and the specified bound criteria. A search key must have been previously constructed /// using JetMakeKey. Returns true if the index range is non-empty, false otherwise. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to position.</param> /// <param name="grbit">Seek option.</param> /// <returns>True if the seek was successful.</returns> public static bool TrySetIndexRange(JET_SESID sesid, JET_TABLEID tableid, SetIndexRangeGrbit grbit) { var err = (JET_err)Impl.JetSetIndexRange(sesid, tableid, grbit); if (JET_err.NoCurrentRecord == err) { return(false); } Api.Check((int)err); Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error"); return(true); }
/// <summary> /// Removes an index range created with <see cref="JetSetIndexRange"/> or /// <see cref="TrySetIndexRange"/>. If no index range is present this /// method does nothing. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to remove the index range on.</param> public static void ResetIndexRange(JET_SESID sesid, JET_TABLEID tableid) { var err = (JET_err)Impl.JetSetIndexRange(sesid, tableid, SetIndexRangeGrbit.RangeRemove); if (JET_err.InvalidOperation == err) { // this error is expected if there isn't currently an index range return; } Api.Check((int)err); return; }
/// <summary> /// Try to move to the next record in the table. If there is not a next record /// this returns false, if a different error is encountered an exception is thrown. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to position.</param> /// <returns>True if the move was successful.</returns> public static bool TryMoveNext(JET_SESID sesid, JET_TABLEID tableid) { var err = (JET_err)Impl.JetMove(sesid, tableid, (int)JET_Move.Next, MoveGrbit.None); if (JET_err.NoCurrentRecord == err) { return(false); } Api.Check((int)err); Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error"); return(true); }
/// <summary> /// Explicitly reserve the ability to update a row, write lock, or to explicitly prevent a row from /// being updated by any other session, read lock. Normally, row write locks are acquired implicitly as a /// result of updating rows. Read locks are usually not required because of record versioning. However, /// in some cases a transaction may desire to explicitly lock a row to enforce serialization, or to ensure /// that a subsequent operation will succeed. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to use. A lock will be acquired on the current record.</param> /// <param name="grbit">Lock options, use this to specify which type of lock to obtain.</param> /// <returns> /// True if the lock was obtained, false otherwise. An exception is thrown if an unexpected /// error is encountered. /// </returns> public static bool TryGetLock(JET_SESID sesid, JET_TABLEID tableid, GetLockGrbit grbit) { var err = (JET_err)Impl.JetGetLock(sesid, tableid, grbit); if (JET_err.WriteConflict == err) { return(false); } Api.Check((int)err); Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error"); return(true); }
/// <summary> /// Retrieves columns into ColumnValue objects. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor retrieve the data from. The cursor should be positioned on a record.</param> /// <param name="values">The values to retrieve.</param> public static void RetrieveColumns(JET_SESID sesid, JET_TABLEID tableid, params ColumnValue[] values) { if (null == values) { throw new ArgumentNullException("values"); } if (0 == values.Length) { throw new ArgumentOutOfRangeException("values", values.Length, "must have at least one value"); } Api.Check(ColumnValue.RetrieveColumns(sesid, tableid, values)); }
/// <summary> /// Retrieve the value for columns whose buffers were truncated. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to use.</param> /// <param name="columnValues">The column values.</param> /// <param name="nativeRetrievecolumns"> /// The native retrieve columns that match the column values. /// </param> private static unsafe void RetrieveTruncatedBuffers(JET_SESID sesid, JET_TABLEID tableid, IList <ColumnValue> columnValues, NATIVE_RETRIEVECOLUMN *nativeRetrievecolumns) { for (int i = 0; i < columnValues.Count; ++i) { if (nativeRetrievecolumns[i].err == (int)JET_wrn.BufferTruncated) { var buffer = new byte[nativeRetrievecolumns[i].cbActual]; int actualSize; int err; var retinfo = new JET_RETINFO { itagSequence = columnValues[i].ItagSequence }; // Pin the buffer and retrieve the data fixed(byte *pinnedBuffer = buffer) { err = Api.Impl.JetRetrieveColumn( sesid, tableid, columnValues[i].Columnid, new IntPtr(pinnedBuffer), buffer.Length, out actualSize, columnValues[i].RetrieveGrbit, retinfo); } if (JET_wrn.BufferTruncated == (JET_wrn)err) { string error = string.Format( CultureInfo.CurrentCulture, "Column size changed from {0} to {1}. The record was probably updated by another thread.", buffer.Length, actualSize); Trace.TraceError(error); throw new InvalidOperationException(error); } // Throw errors, but put warnings in the structure Api.Check(err); columnValues[i].Error = (JET_wrn)err; // For BytesColumnValue this will copy the data to a new array. // If this situation becomes common we should simply use the array. columnValues[i].GetValueFromBytes(buffer, 0, actualSize, err); } } }
/// <summary> /// Retrieves information about indexes on a table. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to retrieve index information about.</param> /// <param name="indexname">The name of the index.</param> /// <param name="result">Filled in with information about indexes on the table.</param> /// <param name="infoLevel">The type of information to retrieve.</param> /// <returns>true if there was no error, false if the index wasn't found. Throws for other Jet errors.</returns> public static bool TryJetGetTableIndexInfo( JET_SESID sesid, JET_TABLEID tableid, string indexname, out JET_INDEXID result, JET_IdxInfo infoLevel) { int err = Impl.JetGetTableIndexInfo(sesid, tableid, indexname, out result, infoLevel); if ((JET_err)err == JET_err.IndexNotFound) { return(false); } Api.Check(err); return(true); }
/// <summary> /// Try to open a table. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="dbid">The database to look for the table in.</param> /// <param name="tablename">The name of the table.</param> /// <param name="grbit">Table open options.</param> /// <param name="tableid">Returns the opened tableid.</param> /// <returns>True if the table was opened, false if the table doesn't exist.</returns> public static bool TryOpenTable( JET_SESID sesid, JET_DBID dbid, string tablename, OpenTableGrbit grbit, out JET_TABLEID tableid) { var err = (JET_err)Impl.JetOpenTable(sesid, dbid, tablename, null, 0, grbit, out tableid); if (JET_err.ObjectNotFound == err) { return(false); } Api.Check((int)err); Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error"); return(true); }
/// <summary> /// Sets columns from ColumnValue objects. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to update. An update should be prepared.</param> /// <param name="values">The values to set.</param> public static void SetColumns(JET_SESID sesid, JET_TABLEID tableid, params ColumnValue[] values) { if (null == values) { throw new ArgumentNullException("values"); } if (0 == values.Length) { throw new ArgumentOutOfRangeException("values", values.Length, "must have at least one value"); } unsafe { NATIVE_SETCOLUMN *nativeSetcolumns = stackalloc NATIVE_SETCOLUMN[values.Length]; Api.Check(values[0].SetColumns(sesid, tableid, values, nativeSetcolumns, 0)); } }
/// <summary> /// Positions a cursor to an index entry for the record that is associated with /// the specified bookmark. The bookmark can be used with any index defined over /// a table. The bookmark for a record can be retrieved using <see cref="JetGetBookmark"/>. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to position.</param> /// <param name="bookmark">The bookmark used to position the cursor.</param> /// <param name="bookmarkSize">The size of the bookmark.</param> /// <returns>True if a record matching the bookmark was found.</returns> public static bool TryGotoBookmark(JET_SESID sesid, JET_TABLEID tableid, byte[] bookmark, int bookmarkSize) { var err = (JET_err)Impl.JetGotoBookmark(sesid, tableid, bookmark, bookmarkSize); // Return false if the record no longer exists. if (JET_err.RecordDeleted == err) { return(false); } // Return false if there is no entry for this record on the current (secondary) index. if (JET_err.NoCurrentRecord == err) { return(false); } Api.Check((int)err); Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error"); return(true); }
/// <summary> /// Retrieve the value for columns whose buffers were truncated. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to use.</param> /// <param name="columnValues">The column values.</param> /// <param name="nativeRetrievecolumns"> /// The native retrieve columns that match the column values. /// </param> private static unsafe void RetrieveTruncatedBuffers(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_RETRIEVECOLUMN *nativeRetrievecolumns) { for (int i = 0; i < columnValues.Length; ++i) { if (nativeRetrievecolumns[i].err == (int)JET_wrn.BufferTruncated) { var buffer = new byte[nativeRetrievecolumns[i].cbActual]; int actualSize; int err; var retinfo = new JET_RETINFO { itagSequence = columnValues[i].ItagSequence }; // Pin the buffer and retrieve the data fixed(byte *pinnedBuffer = buffer) { err = Api.Impl.JetRetrieveColumn( sesid, tableid, columnValues[i].Columnid, new IntPtr(pinnedBuffer), buffer.Length, out actualSize, columnValues[i].RetrieveGrbit, retinfo); } // Set the error in the ColumnValue before checkin it columnValues[i].Error = (JET_err)err; Api.Check(err); // For BytesColumnValue this will copy the data to a new array. // If this situation becomes common we should simply use the array. columnValues[i].GetValueFromBytes(buffer, 0, actualSize, err); } } }
/// <summary> /// Constructs search keys that may then be used by JetSeek and JetSetIndexRange. /// </summary> /// <remarks> /// This is an internal (unsafe) version that takes an IntPtr. /// </remarks> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to create the key on.</param> /// <param name="data">Column data for the current key column of the current index.</param> /// <param name="dataSize">Size of the data.</param> /// <param name="grbit">Key options.</param> internal static void JetMakeKey(JET_SESID sesid, JET_TABLEID tableid, IntPtr data, int dataSize, MakeKeyGrbit grbit) { Api.Check(Impl.JetMakeKey(sesid, tableid, data, dataSize, grbit)); }
/// <summary> /// Retrieves a single column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// Alternatively, this function can retrieve a column from a record being created /// in the cursor copy buffer. This function can also retrieve column data from an /// index entry that references the current record. In addition to retrieving the /// actual column value, JetRetrieveColumn can also be used to retrieve the size /// of a column, before retrieving the column data itself so that application /// buffers can be sized appropriately. /// </summary> /// <remarks> /// This is an internal-use version that takes an IntPtr. /// </remarks> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to retrieve the column from.</param> /// <param name="columnid">The columnid to retrieve.</param> /// <param name="data">The data buffer to be retrieved into.</param> /// <param name="dataSize">The size of the data buffer.</param> /// <param name="actualDataSize">Returns the actual size of the data buffer.</param> /// <param name="grbit">Retrieve column options.</param> /// <param name="retinfo"> /// If pretinfo is give as NULL then the function behaves as though an itagSequence /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to /// retrieve the first value of a multi-valued column, and to retrieve long data at /// offset 0 (zero). /// </param> /// <returns>An ESENT warning code.</returns> internal static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo) { return(Api.Check(Impl.JetRetrieveColumn(sesid, tableid, columnid, data, dataSize, out actualDataSize, grbit, retinfo))); }
/// <summary> /// Recursive RetrieveColumns method for data pinning. This should pin a buffer and /// call the inherited RetrieveColumns method. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid"> /// The table to retrieve the columns from. /// </param> /// <param name="columnValues"> /// Column values to retrieve. /// </param> internal static void RetrieveColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues) { const int MaxColumnValues = 1024; if (columnValues.Length > MaxColumnValues) { throw new ArgumentOutOfRangeException("columnValues", columnValues.Length, "Too many column values"); } unsafe { byte[] buffer = null; NATIVE_RETRIEVECOLUMN *nativeRetrievecolumns = stackalloc NATIVE_RETRIEVECOLUMN[columnValues.Length]; try { buffer = Caches.ColumnCache.Allocate(); Debug.Assert(MaxColumnValues * 16 < buffer.Length, "Maximum size of fixed columns could exceed buffer size"); fixed(byte *pinnedBuffer = buffer) { byte *currentBuffer = pinnedBuffer; int numVariableLengthColumns = columnValues.Length; // First the fixed-size columns for (int i = 0; i < columnValues.Length; ++i) { if (0 != columnValues[i].Size) { columnValues[i].MakeNativeRetrieveColumn(ref nativeRetrievecolumns[i]); nativeRetrievecolumns[i].pvData = new IntPtr(currentBuffer); nativeRetrievecolumns[i].cbData = checked ((uint)columnValues[i].Size); currentBuffer += nativeRetrievecolumns[i].cbData; Debug.Assert(currentBuffer <= pinnedBuffer + buffer.Length, "Moved past end of pinned buffer"); numVariableLengthColumns--; } } // Now the variable-length columns if (numVariableLengthColumns > 0) { int bufferUsed = checked ((int)(currentBuffer - pinnedBuffer)); int bufferRemaining = checked (buffer.Length - bufferUsed); int bufferPerColumn = bufferRemaining / numVariableLengthColumns; Debug.Assert(bufferPerColumn > 0, "Not enough buffer left to retrieve variable length columns"); // Now the variable-size columns for (int i = 0; i < columnValues.Length; ++i) { if (0 == columnValues[i].Size) { columnValues[i].MakeNativeRetrieveColumn(ref nativeRetrievecolumns[i]); nativeRetrievecolumns[i].pvData = new IntPtr(currentBuffer); nativeRetrievecolumns[i].cbData = checked ((uint)bufferPerColumn); currentBuffer += nativeRetrievecolumns[i].cbData; Debug.Assert(currentBuffer <= pinnedBuffer + buffer.Length, "Moved past end of pinned buffer"); } } } // Retrieve the columns Api.Check(Api.Impl.JetRetrieveColumns(sesid, tableid, nativeRetrievecolumns, columnValues.Length)); // Propagate the warnings and output. for (int i = 0; i < columnValues.Length; ++i) { columnValues[i].Error = (JET_wrn)nativeRetrievecolumns[i].err; columnValues[i].ItagSequence = (int)nativeRetrievecolumns[i].itagSequence; } // Now parse out the columns that were retrieved successfully for (int i = 0; i < columnValues.Length; ++i) { if (nativeRetrievecolumns[i].err != (int)JET_wrn.BufferTruncated) { byte *columnBuffer = (byte *)nativeRetrievecolumns[i].pvData; int startIndex = checked ((int)(columnBuffer - pinnedBuffer)); columnValues[i].GetValueFromBytes( buffer, startIndex, checked ((int)nativeRetrievecolumns[i].cbActual), nativeRetrievecolumns[i].err); } } } // Finally retrieve the buffers where the columns weren't large enough. RetrieveTruncatedBuffers(sesid, tableid, columnValues, nativeRetrievecolumns); } finally { if (buffer != null) { Caches.ColumnCache.Free(ref buffer); } } } }
/// <summary> /// The JetSetColumn function modifies a single column value in a modified record to be inserted or to /// update the current record. It can overwrite an existing value, add a new value to a sequence of /// values in a multi-valued column, remove a value from a sequence of values in a multi-valued column, /// or update all or part of a long value, a column of type JET_coltyp.LongText or JET_coltyp.LongBinary. /// </summary> /// <remarks> /// This method takes an IntPtr and is intended for internal use only. /// </remarks> /// <param name="sesid">The session which is performing the update.</param> /// <param name="tableid">The cursor to update. An update should be prepared.</param> /// <param name="columnid">The columnid to set.</param> /// <param name="data">The data to set.</param> /// <param name="dataSize">The size of data to set.</param> /// <param name="grbit">SetColumn options.</param> /// <param name="setinfo">Used to specify itag or long-value offset.</param> /// <returns>A warning value.</returns> internal static JET_wrn JetSetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, SetColumnGrbit grbit, JET_SETINFO setinfo) { return(Api.Check(Impl.JetSetColumn(sesid, tableid, columnid, data, dataSize, grbit, setinfo))); }