/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2009 Oracle. All rights reserved. * */ using System; using System.Collections; using System.Collections.Generic; using System.Text; using BerkeleyDB.Internal; namespace BerkeleyDB { /// <summary> /// A class representing database cursors, which allow for traversal of /// database records. /// </summary> public class Cursor : BaseCursor, IDisposable, IEnumerable<KeyValuePair<DatabaseEntry, DatabaseEntry>> { private KeyValuePair<DatabaseEntry, DatabaseEntry> cur; private KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> curMult; private MultipleKeyDatabaseEntry curMultKey; private DatabaseType dbtype; /// <summary> /// Protected member, storing the pagesize of the underlying database. /// Used during bulk get (i.e. Move*Multiple). /// </summary> protected uint pgsz; /// <summary> /// Specifies where to place duplicate data elements of the key to which /// the cursor refers. /// </summary> public enum InsertLocation { /// <summary> /// The new element appears immediately after the current cursor /// position. /// </summary> AFTER, /// <summary> /// The new element appears immediately before the current cursor /// position. /// </summary> BEFORE, /// <summary> /// The new element appears as the first of the data items for the /// given key /// </summary> FIRST, /// <summary> /// The new element appears as the last of the data items for the /// given key /// </summary> LAST }; /// <summary> /// The key/data pair at which the cursor currently points. /// </summary> /// <remarks> /// Only one of <see cref="Current"/>, <see cref="CurrentMultiple"/> and /// <see cref="CurrentMultipleKey"/> will ever be non-empty. /// </remarks> public KeyValuePair<DatabaseEntry, DatabaseEntry> Current { private set { cur = value; curMult = new KeyValuePair<DatabaseEntry, MultipleDatabaseEntry>(); curMultKey = null; } get { return cur; } } /// <summary> /// The key and multiple data items at which the cursor currently /// points. /// </summary> /// <remarks> /// Only one of <see cref="Current"/>, <see cref="CurrentMultiple"/> and /// <see cref="CurrentMultipleKey"/> will ever be non-empty. /// </remarks> public KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> CurrentMultiple { private set { cur = new KeyValuePair<DatabaseEntry, DatabaseEntry>(); curMult = value; curMultKey = null; } get { return curMult; } } /// <summary> /// The multiple key and data items at which the cursor currently /// points. /// </summary> /// <remarks> /// Only one of <see cref="Current"/>, <see cref="CurrentMultiple"/> and /// <see cref="CurrentMultipleKey"/> will ever be non-empty. /// </remarks> public MultipleKeyDatabaseEntry CurrentMultipleKey { private set { cur = new KeyValuePair<DatabaseEntry, DatabaseEntry>(); curMult = new KeyValuePair<DatabaseEntry, MultipleDatabaseEntry>(); curMultKey = value; } get { return curMultKey; } } private CachePriority _priority; /// <summary> /// The cache priority for pages referenced by the cursor. /// </summary> /// <remarks> /// The priority of a page biases the replacement algorithm to be more /// or less likely to discard a page when space is needed in the buffer /// pool. The bias is temporary, and pages will eventually be discarded /// if they are not referenced again. The setting is only advisory, and /// does not guarantee pages will be treated in a specific way. /// </remarks> public CachePriority Priority { get { return _priority; } set { dbc.set_priority(value.priority); _priority = value; } } internal Cursor(DBC dbc, DatabaseType DbType, uint pagesize) : base(dbc) { pgsz = pagesize; dbtype = DbType; } internal Cursor( DBC dbc, DatabaseType DbType, uint pagesize, CachePriority pri) : base(dbc) { Priority = pri; pgsz = pagesize; dbtype = DbType; } #region Internal API /* These protected methods do the heavy lifting. The API methods for * Cursor and its subclasses call into them, which allows the API * methods to expose subsets of the arg lists, because some args are * optional. */ /* Only BTree and Hash can call this version of Add(). */ /// <summary> /// Protected method for BTree and Hash to insert with KEYFIRST and /// KEYLAST. /// </summary> /// <param name="pair">The key/data pair to add</param> /// <param name="loc">Where to add, if adding duplicate data</param> protected void Add(KeyValuePair<DatabaseEntry, DatabaseEntry> pair, InsertLocation loc) { if (loc == InsertLocation.AFTER) throw new ArgumentException("AFTER may only be specified on Insert()."); if (loc == InsertLocation.BEFORE) throw new ArgumentException("BEFORE may only be specified on Insert()."); Put(pair.Key, pair.Value, (loc == InsertLocation.FIRST) ? DbConstants.DB_KEYFIRST : DbConstants.DB_KEYLAST); } /* Only BTree and Hash can call AddUnique(). */ /// <summary> /// Protected method for BTree and Hash to insert with NODUPDATA. /// </summary> /// <param name="pair">The key/data pair to add</param> protected void AddUnique(KeyValuePair<DatabaseEntry, DatabaseEntry> pair) { Put(pair.Key, pair.Value, DbConstants.DB_NODUPDATA); } /* Only BTree, Hash and Recno can call Insert(). */ /// <summary> /// Protected method for BTree, Hash and Recno to insert with AFTER and /// BEFORE. /// </summary> /// <param name="data">The duplicate data item to add</param> /// <param name="loc"> /// Whether to add the dup data before or after the current cursor /// position /// </param> protected void Insert(DatabaseEntry data, InsertLocation loc) { if (loc == InsertLocation.FIRST) throw new ArgumentException("FIRST may only be specified on Add()."); if (loc == InsertLocation.LAST) throw new ArgumentException("LAST may only be specified on Add()."); DatabaseEntry key = new DatabaseEntry(); Put(key, data, (loc == InsertLocation.AFTER) ? DbConstants.DB_AFTER : DbConstants.DB_BEFORE); } /* * All flavors of get and put boil down to a call to one of these two * methods, just with different flags. */ /// <summary> /// Protected method wrapping DBC->get. /// </summary> /// <param name="key">The key to retrieve</param> /// <param name="data">The data to retrieve</param> /// <param name="flags">Modify the behavior of get</param> /// <param name="info">The locking configuration to use</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> protected bool Get(DatabaseEntry key, DatabaseEntry data, uint flags, LockingInfo info) { flags |= (info == null) ? 0 : info.flags; try { dbc.get(key, data, flags); Current = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data); return true; } catch (NotFoundException) { Current = new KeyValuePair<DatabaseEntry, DatabaseEntry>(); return false; } } /// <summary> /// Protected method wrapping DBC->get for bulk get. /// </summary> /// <param name="key">The key to retrieve</param> /// <param name="data">The data to retrieve</param> /// <param name="BufferSize">Size of the bulk buffer</param> /// <param name="flags">Modify the behavior of get</param> /// <param name="info">The locking configuration to use</param> /// <param name="isMultKey"> /// If true, use DB_MULTIPLE_KEY instead of DB_MULTIPLE /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> protected bool GetMultiple(DatabaseEntry key, DatabaseEntry data, int BufferSize, uint flags, LockingInfo info, bool isMultKey) { int datasz = 0; bool getboth = false; if (flags == DbConstants.DB_GET_BOTH || flags == DbConstants.DB_GET_BOTH_RANGE) { datasz = (int)data.Data.Length; getboth = true; } flags |= (info == null) ? 0 : info.flags; flags |= (isMultKey) ? DbConstants.DB_MULTIPLE_KEY : DbConstants.DB_MULTIPLE; for (; ; ) { if (getboth) { byte[] udata = new byte[BufferSize]; Array.Copy(data.Data, udata, datasz); data.UserData = udata; data.size = (uint)datasz; } else { data.UserData = new byte[BufferSize]; } try { dbc.get(key, data, flags); if (isMultKey) CurrentMultipleKey = new MultipleKeyDatabaseEntry(dbtype, data); else { MultipleDatabaseEntry mult = new MultipleDatabaseEntry(data); CurrentMultiple = new KeyValuePair<DatabaseEntry, MultipleDatabaseEntry>( key, mult); } return true; } catch (NotFoundException) { if (isMultKey) CurrentMultipleKey = null; else CurrentMultiple = new KeyValuePair<DatabaseEntry, MultipleDatabaseEntry>(); return false; } catch (MemoryException) { int sz = (int)data.size; if (sz > BufferSize) BufferSize = sz; else BufferSize *= 2; } } } /// <summary> /// Protected method wrapping DBC->put. /// </summary> /// <param name="key">The key to store</param> /// <param name="data">The data to store</param> /// <param name="flags">Modify the behavior of put</param> protected void Put(DatabaseEntry key, DatabaseEntry data, uint flags) { int ret; ret = dbc.put(key, data, flags); } #endregion Internal API /* * User facing API below. These methods just set the flags as needed * before calling Get or Put. */ /// <summary> /// Stores the key/data pair in the database. /// </summary> /// <remarks> /// If the underlying database supports duplicate data items, and if the /// key already exists in the database and a duplicate sort function has /// been specified, the inserted data item is added in its sorted /// location. If the key already exists in the database and no duplicate /// sort function has been specified, the inserted data item is added as /// the first of the data items for that key. /// </remarks> /// <param name="pair"> /// The key/data pair to be stored in the database. /// </param> public void Add(KeyValuePair<DatabaseEntry, DatabaseEntry> pair) { Put(pair.Key, pair.Value, DbConstants.DB_KEYFIRST); } /// <summary> /// Delete the key/data pair to which the cursor refers. /// </summary> /// <remarks> /// <para> /// The cursor position is unchanged after a delete, and subsequent /// calls to cursor functions expecting the cursor to refer to an /// existing key will fail. /// </para> /// </remarks> /// <exception cref="KeyEmptyException"> /// The element has already been deleted. /// </exception> public new void Delete() { base.Delete(); Current = new KeyValuePair<DatabaseEntry, DatabaseEntry>(); } /// <summary> /// Create a new cursor that uses the same transaction and locker ID as /// the original cursor. /// </summary> /// <remarks> /// This is useful when an application is using locking and requires two /// or more cursors in the same thread of control. /// </remarks> /// <param name="keepPosition"> /// If true, the newly created cursor is initialized to refer to the /// same position in the database as the original cursor (if any) and /// hold the same locks (if any). If false, or the original cursor does /// not hold a database position and locks, the created cursor is /// uninitialized and will behave like a cursor newly created by /// <see cref="BaseDatabase.Cursor"/>.</param> /// <returns>A newly created cursor</returns> public Cursor Duplicate(bool keepPosition) { return new Cursor(dbc.dup( keepPosition ? DbConstants.DB_POSITION : 0), dbtype, pgsz); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// <summary> /// Returns an enumerator that iterates through the /// <see cref="Cursor"/>. /// </summary> /// <remarks> /// The enumerator will begin at the cursor's current position (or the /// first record if the cursor has not yet been positioned) and iterate /// forwards (i.e. in the direction of <see cref="MoveNext"/>) over the /// remaining records. /// </remarks> /// <returns>An enumerator for the Cursor.</returns> public new IEnumerator<KeyValuePair<DatabaseEntry, DatabaseEntry>> GetEnumerator() { while (MoveNext()) yield return Current; } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that pair in <see cref="Current"/>. If the first key has /// duplicate values, the first data item in the set of duplicates is /// stored in <see cref="Current"/>. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirst() { return MoveFirst(null); } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that pair in <see cref="Current"/>. If the first key has /// duplicate values, the first data item in the set of duplicates is /// stored in <see cref="Current"/>. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirst(LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return Get(key, data, DbConstants.DB_FIRST, info); } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that key and as many duplicate data items that can fit in /// a buffer the size of one database page in /// <see cref="CurrentMultiple"/>. /// </summary> /// <overloads> /// If positioning the cursor fails, <see cref="CurrentMultiple"/> will /// contain an empty /// <see cref="KeyValuePair{T,T}"/>. /// </overloads> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirstMultiple() { return MoveFirstMultiple((int)pgsz, null); } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that key and as many duplicate data items that can fit in /// a buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultiple"/>. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirstMultiple(int BufferSize) { return MoveFirstMultiple(BufferSize, null); } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that key and as many duplicate data items that can fit in /// a buffer the size of one database page in /// <see cref="CurrentMultiple"/>. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirstMultiple(LockingInfo info) { return MoveFirstMultiple((int)pgsz, info); } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that key and as many duplicate data items that can fit in /// a buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultiple"/>. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirstMultiple(int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_FIRST, info, false); } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that pair and as many ensuing key/data pairs that can fit /// in a buffer the size of one database page in /// <see cref="CurrentMultipleKey"/>. /// </summary> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirstMultipleKey() { return MoveFirstMultipleKey((int)pgsz, null); } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that pair and as many ensuing key/data pairs that can fit /// in a buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirstMultipleKey(int BufferSize) { return MoveFirstMultipleKey(BufferSize, null); } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that pair and as many ensuing key/data pairs that can fit /// in a buffer the size of one database page in /// <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirstMultipleKey(LockingInfo info) { return MoveFirstMultipleKey((int)pgsz, info); } /// <summary> /// Set the cursor to refer to the first key/data pair of the database, /// and store that pair and as many ensuing key/data pairs that can fit /// in a buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveFirstMultipleKey(int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_FIRST, info, true); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store the /// datum associated with the given key in <see cref="Current"/>. In the /// presence of duplicate key values, the first data item in the set of /// duplicates is stored in <see cref="Current"/>. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool Move(DatabaseEntry key, bool exact) { return Move(key, exact, null); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store the /// datum associated with the given key in <see cref="Current"/>. In the /// presence of duplicate key values, the first data item in the set of /// duplicates is stored in <see cref="Current"/>. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool Move(DatabaseEntry key, bool exact, LockingInfo info) { DatabaseEntry data = new DatabaseEntry(); return Get(key, data, exact ? DbConstants.DB_SET : DbConstants.DB_SET_RANGE, info); } /// <summary> /// Move the cursor to the specified key/data pair of the database. The /// cursor is positioned to a key/data pair if both the key and data /// match the values provided on the key and data parameters. /// </summary> /// <remarks> /// <para> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </para> /// <para> /// If this flag is specified on a database configured without sorted /// duplicate support, the value of <paramref name="exact"/> is ignored. /// </para> /// </remarks> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool Move( KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact) { return Move(pair, exact, null); } /// <summary> /// Move the cursor to the specified key/data pair of the database. The /// cursor is positioned to a key/data pair if both the key and data /// match the values provided on the key and data parameters. /// </summary> /// <remarks> /// <para> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </para> /// <para> /// If this flag is specified on a database configured without sorted /// duplicate support, the value of <paramref name="exact"/> is ignored. /// </para> /// </remarks> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool Move(KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact, LockingInfo info) { return Get(pair.Key, pair.Value, exact ? DbConstants.DB_GET_BOTH : DbConstants.DB_GET_BOTH_RANGE, info); } /// <summary> /// Set the cursor to refer to the last key/data pair of the database, /// and store that pair in <see cref="Current"/>. If the last key has /// duplicate values, the last data item in the set of duplicates is /// stored in <see cref="Current"/>. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveLast() { return MoveLast(null); } /// <summary> /// Set the cursor to refer to the last key/data pair of the database, /// and store that pair in <see cref="Current"/>. If the last key has /// duplicate values, the last data item in the set of duplicates is /// stored in <see cref="Current"/>. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveLast(LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return Get(key, data, DbConstants.DB_LAST, info); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store that /// key and as many duplicate data items associated with the given key that /// can fit in a buffer the size of one database page in /// <see cref="CurrentMultiple"/>. /// </summary> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultiple(DatabaseEntry key, bool exact) { return MoveMultiple(key, exact, (int)pgsz, null); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store that /// key and as many duplicate data items associated with the given key that /// can fit in a buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultiple"/>. /// </summary> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultiple( DatabaseEntry key, bool exact, int BufferSize) { return MoveMultiple(key, exact, BufferSize, null); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store that /// key and as many duplicate data items associated with the given key that /// can fit in a buffer the size of one database page in /// <see cref="CurrentMultiple"/>. /// </summary> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultiple( DatabaseEntry key, bool exact, LockingInfo info) { return MoveMultiple(key, exact, (int)pgsz, info); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store that /// key and as many duplicate data items associated with the given key that /// can fit in a buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultiple"/>. /// </summary> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultiple( DatabaseEntry key, bool exact, int BufferSize, LockingInfo info) { DatabaseEntry data = new DatabaseEntry(); return GetMultiple(key, data, BufferSize, (exact ? DbConstants.DB_SET : DbConstants.DB_SET_RANGE), info, false); } /// <summary> /// Move the cursor to the specified key/data pair of the database, and /// store that key/data pair and as many duplicate data items associated /// with the given key that can fit in a buffer the size of one database /// page in <see cref="CurrentMultiple"/>. The cursor is positioned to a /// key/data pair if both the key and data match the values provided on /// the key and data parameters. /// </summary> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultiple( KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact) { return MoveMultiple(pair, exact, (int)pgsz, null); } /// <summary> /// Move the cursor to the specified key/data pair of the database, and /// store that key/data pair and as many duplicate data items associated /// with the given key that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultiple"/>. The /// cursor is positioned to a key/data pair if both the key and data /// match the values provided on the key and data parameters. /// </summary> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultiple( KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact, int BufferSize) { return MoveMultiple(pair, exact, BufferSize, null); } /// <summary> /// Move the cursor to the specified key/data pair of the database, and /// store that key/data pair and as many duplicate data items associated /// with the given key that can fit in a buffer the size of one database /// page in <see cref="CurrentMultiple"/>. The cursor is positioned to a /// key/data pair if both the key and data match the values provided on /// the key and data parameters. /// </summary> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultiple( KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact, LockingInfo info) { return MoveMultiple(pair, exact, (int)pgsz, info); } /// <summary> /// Move the cursor to the specified key/data pair of the database, and /// store that key/data pair and as many duplicate data items associated /// with the given key that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultiple"/>. The /// cursor is positioned to a key/data pair if both the key and data /// match the values provided on the key and data parameters. /// </summary> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultiple( KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact, int BufferSize, LockingInfo info) { return GetMultiple(pair.Key, pair.Value, BufferSize, (exact ? DbConstants.DB_GET_BOTH : DbConstants.DB_GET_BOTH_RANGE), info, false); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store that /// key and as many ensuing key/data pairs that can fit in a buffer the /// size of one database page in <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultipleKey(DatabaseEntry key, bool exact) { return MoveMultipleKey(key, exact, (int)pgsz, null); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store that /// key and as many ensuing key/data pairs that can fit in a buffer the /// size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultipleKey( DatabaseEntry key, bool exact, int BufferSize) { return MoveMultipleKey(key, exact, BufferSize, null); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store that /// key and as many ensuing key/data pairs that can fit in a buffer the /// size of one database page in <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultipleKey( DatabaseEntry key, bool exact, LockingInfo info) { return MoveMultipleKey(key, exact, (int)pgsz, info); } /// <summary> /// Set the cursor to refer to <paramref name="key"/>, and store that /// key and as many ensuing key/data pairs that can fit in a buffer the /// size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="key">The key at which to position the cursor</param> /// <param name="exact"> /// If true, require the given key to match the key in the database /// exactly. If false, position the cursor at the smallest key greater /// than or equal to the specified key, permitting partial key matches /// and range searches. /// </param> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultipleKey( DatabaseEntry key, bool exact, int BufferSize, LockingInfo info) { DatabaseEntry data = new DatabaseEntry(); return GetMultiple(key, data, BufferSize, (exact ? DbConstants.DB_SET : DbConstants.DB_SET_RANGE), info, true); } /// <summary> /// Move the cursor to the specified key/data pair of the database, and /// store that key/data pair and as many ensuing key/data pairs that can /// fit in a buffer the size of one database page in /// <see cref="CurrentMultipleKey"/>. The cursor is positioned to a /// key/data pair if both the key and data match the values provided on /// the key and data parameters. /// </summary> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultipleKey( KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact) { return MoveMultipleKey(pair, exact, (int)pgsz, null); } /// <summary> /// Move the cursor to the specified key/data pair of the database, and /// store that key/data pair and as many ensuing key/data pairs that can /// fit in a buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultipleKey"/>. The cursor is positioned to a /// key/data pair if both the key and data match the values provided on /// the key and data parameters. /// </summary> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultipleKey( KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact, int BufferSize) { return MoveMultipleKey(pair, exact, BufferSize, null); } /// <summary> /// Move the cursor to the specified key/data pair of the database, and /// store that key/data pair and as many ensuing key/data pairs that can /// fit in a buffer the size of one database page in /// <see cref="CurrentMultipleKey"/>. The cursor is positioned to a /// key/data pair if both the key and data match the values provided on /// the key and data parameters. /// </summary> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultipleKey( KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact, LockingInfo info) { return MoveMultipleKey(pair, exact, (int)pgsz, info); } /// <summary> /// Move the cursor to the specified key/data pair of the database, and /// store that key/data pair and as many ensuing key/data pairs that can /// fit in a buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultipleKey"/>. The cursor is positioned to a /// key/data pair if both the key and data match the values provided on /// the key and data parameters. /// </summary> /// <param name="pair"> /// The key/data pair at which to position the cursor. /// </param> /// <param name="exact"> /// If true, require the given key and data to match the key and data /// in the database exactly. If false, position the cursor at the /// smallest data value which is greater than or equal to the value /// provided by <paramref name="pair.Value"/> (as determined by the /// comparison function). /// </param> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveMultipleKey( KeyValuePair<DatabaseEntry, DatabaseEntry> pair, bool exact, int BufferSize, LockingInfo info) { return GetMultiple(pair.Key, pair.Value, BufferSize, (exact ? DbConstants.DB_GET_BOTH : DbConstants.DB_GET_BOTH_RANGE), info, true); } /// <summary> /// If the cursor is not yet initialized, MoveNext is identical to /// <see cref="MoveFirst()"/>. Otherwise, move the cursor to the next /// key/data pair of the database, and store that pair in /// <see cref="Current"/>. In the presence of duplicate key values, the /// value of <see cref="Current">Current.Key</see> may not change. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNext() { return MoveNext(null); } /// <summary> /// If the cursor is not yet initialized, MoveNext is identical to /// <see cref="MoveFirst(LockingInfo)"/>. Otherwise, move the cursor to /// the next key/data pair of the database, and store that pair in /// <see cref="Current"/>. In the presence of duplicate key values, the /// value of <see cref="Current">Current.Key</see> may not change. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNext(LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return Get(key, data, DbConstants.DB_NEXT, info); } /// <summary> /// If the cursor is not yet initialized, MoveNextMultiple is identical /// to <see cref="MoveFirstMultiple()"/>. Otherwise, move the cursor to /// the next key/data pair of the database, and store that pair and as /// many duplicate data items that can fit in a buffer the size of one /// database page in <see cref="CurrentMultiple"/>. In the presence of /// duplicate key values, the value of /// <see cref="CurrentMultiple">CurrentMultiple.Key</see> may not /// change. /// </summary> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextMultiple() { return MoveNextMultiple((int)pgsz, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextMultiple is identical /// to <see cref="MoveFirstMultiple(int)"/>. Otherwise, move the cursor /// to the next key/data pair of the database, and store that pair and /// as many duplicate data items that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultiple"/>. In /// the presence of duplicate key values, the value of /// <see cref="CurrentMultiple">CurrentMultiple.Key</see> may not /// change. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextMultiple(int BufferSize) { return MoveNextMultiple(BufferSize, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextMultiple is identical /// to <see cref="MoveFirstMultiple(LockingInfo)"/>. Otherwise, move the /// cursor to the next key/data pair of the database, and store that /// pair and as many duplicate data items that can fit in a buffer the /// size of one database page in <see cref="CurrentMultiple"/>. In the /// presence of duplicate key values, the value of /// <see cref="CurrentMultiple">CurrentMultiple.Key</see> may not /// change. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextMultiple(LockingInfo info) { return MoveNextMultiple((int)pgsz, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextMultiple is identical /// to <see cref="MoveFirstMultiple(int, LockingInfo)"/>. Otherwise, /// move the cursor to the next key/data pair of the database, and store /// that pair and as many duplicate data items that can fit in a buffer /// the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultiple"/>. In the presence of duplicate key /// values, the value of /// <see cref="CurrentMultiple">CurrentMultiple.Key</see> may not /// change. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextMultiple(int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_NEXT, info, false); } /// <summary> /// If the cursor is not yet initialized, MoveNextMultipleKey is /// identical to <see cref="MoveFirstMultipleKey()"/>. Otherwise, move /// the cursor to the next key/data pair of the database, and store that /// pair and as many ensuing key/data pairs that can fit in a buffer the /// size of one database page in <see cref="CurrentMultipleKey"/>. In /// the presence of duplicate key values, the keys of /// <see cref="CurrentMultipleKey"/> may not change. /// </summary> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextMultipleKey() { return MoveNextMultipleKey((int)pgsz, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextMultipleKey is /// identical to <see cref="MoveFirstMultipleKey(int)"/>. Otherwise, /// move the cursor to the next key/data pair of the database, and store /// that pair and as many ensuing key/data pairs that can fit in a /// buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultipleKey"/>. In the presence of duplicate key /// values, the keys of <see cref="CurrentMultipleKey"/> may not change. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextMultipleKey(int BufferSize) { return MoveNextMultipleKey(BufferSize, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextMultipleKey is /// identical to <see cref="MoveFirstMultipleKey(LockingInfo)"/>. /// Otherwise, move the cursor to the next key/data pair of the /// database, and store that pair and as many ensuing key/data pairs /// that can fit in a buffer the size of one database page in /// <see cref="CurrentMultipleKey"/>. In the presence of duplicate key /// values, the keys of <see cref="CurrentMultipleKey"/> may not change. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextMultipleKey(LockingInfo info) { return MoveNextMultipleKey((int)pgsz, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextMultipleKey is /// identical to <see cref="MoveFirstMultipleKey(int, LockingInfo)"/>. /// Otherwise, move the cursor to the next key/data pair of the /// database, and store that pair and as many ensuing key/data pairs /// that can fit in a buffer the size of <paramref name="BufferSize"/> /// in <see cref="CurrentMultipleKey"/>. In the presence of duplicate /// key values, the keys of <see cref="CurrentMultipleKey"/> may not /// change. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextMultipleKey(int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_NEXT, info, true); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, move the cursor to the next key/data /// pair in the database, and store that pair in <see cref="Current"/>. /// MoveNextDuplicate will return false if the next key/data pair of the /// database is not a duplicate data record for the current key/data /// pair. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicate() { return MoveNextDuplicate(null); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, move the cursor to the next key/data /// pair in the database, and store that pair in <see cref="Current"/>. /// MoveNextDuplicate will return false if the next key/data pair of the /// database is not a duplicate data record for the current key/data /// pair. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicate(LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return Get(key, data, DbConstants.DB_NEXT_DUP, info); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, move the cursor to the next key/data /// pair in the database, and store that pair and as many duplicate data /// items that can fit in a buffer the size of one database page in /// <see cref="CurrentMultiple"/>. MoveNextDuplicateMultiple will return /// false if the next key/data pair of the database is not a duplicate /// data record for the current key/data pair. /// </summary> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicateMultiple() { return MoveNextDuplicateMultiple((int)pgsz, null); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, then move cursor to the next key/data /// pair in the database, and store that pair and as many duplicate data /// items that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultiple"/>. /// MoveNextDuplicateMultiple will return false if the next key/data /// pair of the database is not a duplicate data record for the current /// key/data pair. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicateMultiple(int BufferSize) { return MoveNextDuplicateMultiple(BufferSize, null); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, move the cursor to the next key/data /// pair in the database, and store that pair and as many duplicate data /// items that can fit in a buffer the size of one database page in /// <see cref="CurrentMultiple"/>. MoveNextDuplicateMultiple will return /// false if the next key/data pair of the database is not a duplicate /// data record for the current key/data pair. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicateMultiple(LockingInfo info) { return MoveNextDuplicateMultiple((int)pgsz, info); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, move the cursor to the next key/data /// pair in the database, and store that pair and as many duplicate data /// items that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultiple"/>. /// MoveNextDuplicateMultiple will return false if the next key/data /// pair of the database is not a duplicate data record for the current /// key/data pair. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicateMultiple( int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_NEXT_DUP, info, false); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, move the cursor to the next key/data /// pair in the database, and store that pair and as many duplicate data /// items that can fit in a buffer the size of one database page in /// <see cref="CurrentMultipleKey"/>. MoveNextDuplicateMultipleKey will /// return false if the next key/data pair of the database is not a /// duplicate data record for the current key/data pair. /// </summary> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicateMultipleKey() { return MoveNextDuplicateMultipleKey((int)pgsz, null); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, move the cursor to the next key/data /// pair in the database, and store that pair and as many duplicate data /// items that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultipleKey"/>. /// MoveNextDuplicateMultipleKey will return false if the next key/data /// pair of the database is not a duplicate data record for the current /// key/data pair. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicateMultipleKey(int BufferSize) { return MoveNextDuplicateMultipleKey(BufferSize, null); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, move the cursor to the next key/data /// pair in the database, and store that pair and as many duplicate data /// items that can fit in a buffer the size of one database page in /// <see cref="CurrentMultipleKey"/>. MoveNextDuplicateMultipleKey will /// return false if the next key/data pair of the database is not a /// duplicate data record for the current key/data pair. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicateMultipleKey(LockingInfo info) { return MoveNextDuplicateMultipleKey((int)pgsz, info); } /// <summary> /// If the next key/data pair of the database is a duplicate data record /// for the current key/data pair, move the cursor to the next key/data /// pair in the database, and store that pair and as many duplicate data /// items that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultipleKey"/>. /// MoveNextDuplicateMultipleKey will return false if the next key/data /// pair of the database is not a duplicate data record for the current /// key/data pair. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextDuplicateMultipleKey( int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_NEXT_DUP, info, true); } /// <summary> /// If the cursor is not yet initialized, MoveNextUnique is identical to /// <see cref="MoveFirst()"/>. Otherwise, move the cursor to the next /// non-duplicate key in the database, and store that key and associated /// datum in <see cref="Current"/>. MoveNextUnique will return false if /// no non-duplicate key/data pairs exist after the cursor position in /// the database. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUnique() { return MoveNextUnique(null); } /// <summary> /// If the cursor is not yet initialized, MoveNextUnique is identical to /// <see cref="MoveFirst(LockingInfo)"/>. Otherwise, move the cursor to /// the next non-duplicate key in the database, and store that key and /// associated datum in <see cref="Current"/>. MoveNextUnique will /// return false if no non-duplicate key/data pairs exist after the /// cursor position in the database. /// </summary> /// <remarks> /// <para> /// If the database is a Queue or Recno database, MoveNextUnique will /// ignore any keys that exist but were never explicitly created by the /// application, or those that were created and later deleted. /// </para> /// <para> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </para> /// </remarks> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUnique(LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return Get(key, data, DbConstants.DB_NEXT_NODUP, info); } /// <summary> /// If the cursor is not yet initialized, MoveNextUniqueMultiple is /// identical to <see cref="MoveFirstMultiple()"/>. Otherwise, move the /// cursor to the next non-duplicate key in the database, and store that /// key and associated datum and as many duplicate data items that can /// fit in a buffer the size of one database page in /// <see cref="CurrentMultiple"/>. MoveNextUniqueMultiple will return /// false if no non-duplicate key/data pairs exist after the cursor /// position in the database. /// </summary> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUniqueMultiple() { return MoveNextUniqueMultiple((int)pgsz, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextUniqueMultiple is /// identical to <see cref="MoveFirstMultiple(int)"/>. Otherwise, move /// the cursor to the next non-duplicate key in the database, and store /// that key and associated datum and as many duplicate data items that /// can fit in a buffer the size of <paramref name="BufferSize"/> in /// <see cref="CurrentMultiple"/>. MoveNextUniqueMultiple will return /// false if no non-duplicate key/data pairs exist after the cursor /// position in the database. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUniqueMultiple(int BufferSize) { return MoveNextUniqueMultiple(BufferSize, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextUniqueMultiple is /// identical to <see cref="MoveFirstMultiple(LockingInfo)"/>. /// Otherwise, move the cursor to the next non-duplicate key in the /// database, and store that key and associated datum and as many /// duplicate data items that can fit in a buffer the size of one /// database page in <see cref="CurrentMultiple"/>. /// MoveNextUniqueMultiple will return false if no non-duplicate /// key/data pairs exist after the cursor position in the database. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUniqueMultiple(LockingInfo info) { return MoveNextUniqueMultiple((int)pgsz, info); } /// <summary> /// If the cursor is not yet initialized, MoveNextUniqueMultiple is /// identical to <see cref="MoveFirstMultiple(int, LockingInfo)"/>. /// Otherwise, move the cursor to the next non-duplicate key in the /// database, and store that key and associated datum and as many /// duplicate data items that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultiple"/>. /// MoveNextUniqueMultiple will return false if no non-duplicate /// key/data pairs exist after the cursor position in the database. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUniqueMultiple(int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_NEXT_NODUP, info, false); } /// <summary> /// If the cursor is not yet initialized, MoveNextUniqueMultipleKey is /// identical to <see cref="MoveFirstMultipleKey()"/>. Otherwise, move /// the cursor to the next non-duplicate key in the database, and store /// that key and associated datum and as many ensuing key/data pairs /// that can fit in a buffer the size of one database page in /// <see cref="CurrentMultipleKey"/>. MoveNextUniqueMultipleKey will /// return false if no non-duplicate key/data pairs exist after the /// cursor position in the database. /// </summary> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUniqueMultipleKey() { return MoveNextUniqueMultipleKey((int)pgsz, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextUniqueMultipleKey is /// identical to <see cref="MoveFirstMultipleKey(int)"/>. Otherwise, /// move the cursor to the next non-duplicate key in the database, and /// store that key and associated datum and as many ensuing key/data /// pairs that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultipleKey"/>. /// MoveNextUniqueMultipleKey will return false if no non-duplicate /// key/data pairs exist after the cursor position in the database. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUniqueMultipleKey(int BufferSize) { return MoveNextUniqueMultipleKey(BufferSize, null); } /// <summary> /// If the cursor is not yet initialized, MoveNextUniqueMultipleKey is /// identical to <see cref="MoveFirstMultipleKey(LockingInfo)"/>. /// Otherwise, move the cursor to the next non-duplicate key in the /// database, and store that key and associated datum and as many /// ensuing key/data pairs that can fit in a buffer the size of one /// database page in <see cref="CurrentMultipleKey"/>. /// MoveNextUniqueMultipleKey will return false if no non-duplicate /// key/data pairs exist after the cursor position in the database. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUniqueMultipleKey(LockingInfo info) { return MoveNextUniqueMultipleKey((int)pgsz, info); } /// <summary> /// If the cursor is not yet initialized, MoveNextUniqueMultipleKey is /// identical to <see cref="MoveFirstMultipleKey(int, LockingInfo)"/>. /// Otherwise, move the cursor to the next non-duplicate key in the /// database, and store that key and associated datum and as many /// ensuing key/data pairs that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultipleKey"/>. /// MoveNextUniqueMultipleKey will return false if no non-duplicate /// key/data pairs exist after the cursor position in the database. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MoveNextUniqueMultipleKey( int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_NEXT_NODUP, info, true); } /// <summary> /// If the cursor is not yet initialized, MovePrev is identical to /// <see cref="MoveLast()"/>. Otherwise, move the cursor to the previous /// key/data pair of the database, and store that pair in /// <see cref="Current"/>. In the presence of duplicate key values, the /// value of <see cref="Current">Current.Key</see> may not change. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MovePrev() { return MovePrev(null); } /// <summary> /// If the cursor is not yet initialized, MovePrev is identical to /// <see cref="MoveLast(LockingInfo)"/>. Otherwise, move the cursor to /// the previous key/data pair of the database, and store that pair in /// <see cref="Current"/>. In the presence of duplicate key values, the /// value of <see cref="Current">Current.Key</see> may not change. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MovePrev(LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return Get(key, data, DbConstants.DB_PREV, info); } /// <summary> /// If the previous key/data pair of the database is a duplicate data /// record for the current key/data pair, the cursor is moved to the /// previous key/data pair of the database, and that pair is stored in /// <see cref="Current"/>. MovePrevDuplicate will return false if the /// previous key/data pair of the database is not a duplicate data /// record for the current key/data pair. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MovePrevDuplicate() { return MovePrevDuplicate(null); } /// <summary> /// If the previous key/data pair of the database is a duplicate data /// record for the current key/data pair, the cursor is moved to the /// previous key/data pair of the database, and that pair is stored in /// <see cref="Current"/>. MovePrevDuplicate will return false if the /// previous key/data pair of the database is not a duplicate data /// record for the current key/data pair. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MovePrevDuplicate(LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return Get(key, data, DbConstants.DB_PREV_DUP, info); } /// <summary> /// If the cursor is not yet initialized, MovePrevUnique is identical to /// <see cref="MoveLast()"/>. Otherwise, move the cursor to the previous /// non-duplicate key in the database, and store that key and associated /// datum in <see cref="Current"/>. MovePrevUnique will return false if /// no non-duplicate key/data pairs exist after the cursor position in /// the database. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MovePrevUnique() { return MovePrevUnique(null); } /// <summary> /// If the cursor is not yet initialized, MovePrevUnique is identical to /// <see cref="MoveLast(LockingInfo)"/>. Otherwise, move the cursor to /// the previous non-duplicate key in the database, and store that key /// and associated datum in <see cref="Current"/>. MovePrevUnique will /// return false if no non-duplicate key/data pairs exist after the /// cursor position in the database. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool MovePrevUnique(LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return Get(key, data, DbConstants.DB_PREV_NODUP, info); } /// <summary> /// Overwrite the data of the key/data pair to which the cursor refers /// with the specified data item. /// </summary> /// <param name="data"></param> public void Overwrite(DatabaseEntry data) { DatabaseEntry key = new DatabaseEntry(); Put(key, data, DbConstants.DB_CURRENT); } /// <summary> /// Store the key/data pair to which the cursor refers in /// <see cref="Current"/>. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool Refresh() { return Refresh(null); } /// <summary> /// Store the key/data pair to which the cursor refers in /// <see cref="Current"/>. /// </summary> /// <remarks> /// If positioning the cursor fails, <see cref="Current"/> will contain /// an empty <see cref="KeyValuePair{T,T}"/>. /// </remarks> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool Refresh(LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return Get(key, data, DbConstants.DB_CURRENT, info); } /// <summary> /// Store the key/data pair to which the cursor refers and as many /// duplicate data items that can fit in a buffer the size of one /// database page in <see cref="CurrentMultiple"/>. /// </summary> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool RefreshMultiple() { return RefreshMultiple((int)pgsz, null); } /// <summary> /// Store the key/data pair to which the cursor refers and as many /// duplicate data items that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultiple"/>. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool RefreshMultiple(int BufferSize) { return RefreshMultiple(BufferSize, null); } /// <summary> /// Store the key/data pair to which the cursor refers and as many /// duplicate data items that can fit in a buffer the size of one /// database page in <see cref="CurrentMultiple"/>. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool RefreshMultiple(LockingInfo info) { return RefreshMultiple((int)pgsz, info); } /// <summary> /// Store the key/data pair to which the cursor refers and as many /// duplicate data items that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultiple"/>. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with duplicate data items. Must be at /// least the page size of the underlying database and be a multiple of /// 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool RefreshMultiple(int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_CURRENT, info, false); } /// <summary> /// Store the key/data pair to which the cursor refers and as many /// ensuing key/data pairs that can fit in a buffer the size of one /// database page in <see cref="CurrentMultipleKey"/>. /// </summary> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool RefreshMultipleKey() { return RefreshMultipleKey((int)pgsz, null); } /// <summary> /// Store the key/data pair to which the cursor refers and as many /// ensuing key/data pairs that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool RefreshMultipleKey(int BufferSize) { return RefreshMultipleKey(BufferSize, null); } /// <summary> /// Store the key/data pair to which the cursor refers and as many /// ensuing key/data pairs that can fit in a buffer the size of one /// database page in <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool RefreshMultipleKey(LockingInfo info) { return RefreshMultipleKey((int)pgsz, info); } /// <summary> /// Store the key/data pair to which the cursor refers and as many /// ensuing key/data pairs that can fit in a buffer the size of /// <paramref name="BufferSize"/> in <see cref="CurrentMultipleKey"/>. /// </summary> /// <param name="BufferSize"> /// The size of a buffer to fill with key/data pairs. Must be at least /// the page size of the underlying database and be a multiple of 1024. /// </param> /// <param name="info">The locking behavior to use.</param> /// <returns> /// True if the cursor was positioned successfully, false otherwise. /// </returns> public bool RefreshMultipleKey(int BufferSize, LockingInfo info) { DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); return GetMultiple( key, data, BufferSize, DbConstants.DB_CURRENT, info, true); } } }