/// <summary> /// Creates and attaches a database file. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="database">The path to the database file to create.</param> /// <param name="dbid">Returns the dbid of the new database.</param> /// <param name="grbit">Database creation options.</param> public static void CreateDatabase(JET_SESID sesid, string database, out JET_DBID dbid, CreateDatabaseGrbit grbit) { Api.JetCreateDatabase(sesid, database, null, out dbid, grbit); }
/// <summary> /// Position the cursor before the first record in the table. A /// subsequent move next will position the cursor on the first /// record. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to position.</param> public static void MoveBeforeFirst(JET_SESID sesid, JET_TABLEID tableid) { Api.TryMoveFirst(sesid, tableid); Api.TryMovePrevious(sesid, tableid); }
/// <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) { return(TryMove(sesid, tableid, JET_Move.Next, MoveGrbit.None)); }
/// <summary> /// Initializes a new instance of the InstanceParameters class. /// </summary> /// <param name="instance">The instance to set parameters on.</param> public InstanceParameters(JET_INSTANCE instance) { this.instance = instance; this.sesid = JET_SESID.Nil; }
/// <summary> /// Initializes a new instance of the Transaction class. This automatically /// begins a transaction. The transaction will be rolled back if /// not explicitly committed. /// </summary> /// <param name="sesid">The session to start the transaction for.</param> public Transaction(JET_SESID sesid) { this.sesid = sesid; this.Begin(); }
public static ulong?RetrieveColumnAsUInt64(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid) { return(RetrieveColumnAsUInt64(sesid, tableid, columnid, RetrieveColumnGrbit.None)); }
/// <summary> /// Constructs a search key that may then be used by <see cref="JetSeek"/> /// and <see cref="JetSetIndexRange"/>. /// </summary> /// <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="grbit">Key options.</param> public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, bool data, MakeKeyGrbit grbit) { byte b = data ? (byte)0xff : (byte)0x0; Api.MakeKey(sesid, tableid, b, grbit); }
/// <summary> /// Modifies a single column value in a modified record to be inserted or to /// update the current record. /// </summary> /// <param name="sesid">The session to use.</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> public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data) { SetColumn(sesid, tableid, columnid, data, SetColumnGrbit.None); }
/// <summary> /// Modifies a single column value in a modified record to be inserted or to /// update the current record. /// </summary> /// <param name="sesid">The session to use.</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> public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, bool data) { byte b = data ? (byte)0xff : (byte)0x0; SetColumn(sesid, tableid, columnid, b); }
/// <summary> /// Recursive SetColumns method for data pinning. This should populate the buffer and /// call the inherited SetColumns method. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid"> /// The table to set the columns in. An update should be prepared. /// </param> /// <param name="columnValues"> /// Column values to set. /// </param> /// <param name="nativeColumns"> /// Structures to put the pinned data in. /// </param> /// <param name="i">Offset of this object in the array.</param> /// <returns>An error code.</returns> internal abstract unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN *nativeColumns, int i);
/// <summary> /// Initializes a new instance of the <see cref="TableEnumerator{T}"/> class. /// </summary> /// <param name="sesid"> /// The session to use. /// </param> protected TableEnumerator(JET_SESID sesid) { this.Sesid = sesid; this.TableidToEnumerate = JET_TABLEID.Nil; }
/// <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> /// Modifies a single column value in a modified record to be inserted or to /// update the current record. /// </summary> /// <param name="sesid">The session to use.</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="encoding">The encoding used to convert the string.</param> /// <param name="grbit">SetColumn options.</param> public static void SetColumn( JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, string data, Encoding encoding, SetColumnGrbit grbit) { CheckEncodingIsValid(encoding); if (null == data) { JetSetColumn(sesid, tableid, columnid, null, 0, grbit, null); } else if (0 == data.Length) { JetSetColumn(sesid, tableid, columnid, null, 0, grbit | SetColumnGrbit.ZeroLength, null); } else if (Encoding.Unicode == encoding) { // Optimization for setting Unicode strings. unsafe { fixed(char *buffer = data) { JetSetColumn( sesid, tableid, columnid, new IntPtr(buffer), checked (data.Length * sizeof(char)), grbit, null); } } } else if (encoding.GetMaxByteCount(data.Length) <= Caches.ColumnCache.BufferSize) { #if MANAGEDESENT_ON_WSA // Encoding.GetBytes(char*, int, byte*, int) overload is missing in new Windows UI. // So we can't use the ColumnCache. We'll just use a different GetBytes() overload. byte[] buffer = encoding.GetBytes(data); unsafe { fixed(byte *bytes = buffer) { JetSetColumn(sesid, tableid, columnid, new IntPtr(bytes), buffer.Length, grbit, null); } } #else // The encoding output will fix in a cached buffer. Get one to avoid // more memory allocations. byte[] buffer = null; try { buffer = Caches.ColumnCache.Allocate(); unsafe { fixed(char *chars = data) fixed(byte *bytes = buffer) { int dataSize = encoding.GetBytes(chars, data.Length, bytes, buffer.Length); JetSetColumn(sesid, tableid, columnid, new IntPtr(bytes), dataSize, grbit, null); } } } finally { if (buffer != null) { Caches.ColumnCache.Free(ref buffer); } } #endif } else { byte[] bytes = encoding.GetBytes(data); JetSetColumn(sesid, tableid, columnid, bytes, bytes.Length, grbit, null); } }
/// <summary> /// Initializes a new instance of the <see cref="ColumnInfoEnumerator"/> class. /// </summary> /// <param name="sesid"> /// The session to use. /// </param> protected ColumnInfoEnumerator(JET_SESID sesid) : base(sesid) { }
/// <summary> /// Retrieves a guid column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// </summary> /// <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> /// <returns>The data retrieved from the column as a guid. Null if the column is null.</returns> public static Guid?RetrieveColumnAsGuid(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid) { return(RetrieveColumnAsGuid(sesid, tableid, columnid, RetrieveColumnGrbit.None)); }
/// <summary> /// Modifies a single column value in a modified record to be inserted or to /// update the current record. /// </summary> /// <param name="sesid">The session to use.</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> public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, DateTime data) { SetColumn(sesid, tableid, columnid, data.ToOADate()); }
/// <summary> /// Retrieves a datetime column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// </summary> /// <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> /// <returns>The data retrieved from the column as a datetime. Null if the column is null.</returns> public static DateTime?RetrieveColumnAsDateTime(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid) { return(RetrieveColumnAsDateTime(sesid, tableid, columnid, RetrieveColumnGrbit.None)); }
/// <summary> /// Modifies a single column value in a modified record to be inserted or to /// update the current record. /// </summary> /// <param name="sesid">The session to use.</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="encoding">The encoding used to convert the string.</param> public static void SetColumn( JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, string data, Encoding encoding) { SetColumn(sesid, tableid, columnid, data, encoding, SetColumnGrbit.None); }
/// <summary> /// Deserialize an object from a column. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to read from.</param> /// <param name="columnid">The column to read from.</param> /// <returns>The deserialized object. Null if the column was null.</returns> public static object DeserializeObjectFromColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid) { return(DeserializeObjectFromColumn(sesid, tableid, columnid, RetrieveColumnGrbit.None)); }
/// <summary> /// Retrieves the size of 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. /// </summary> /// <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> /// <returns>The size of the column. 0 if the column is null.</returns> public static int?RetrieveColumnSize(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid) { return(RetrieveColumnSize(sesid, tableid, columnid, 1, RetrieveColumnGrbit.None)); }
/// <summary> /// Constructs a search key that may then be used by <see cref="JetSeek"/> /// and <see cref="JetSetIndexRange"/>. /// </summary> /// <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="grbit">Key options.</param> public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, DateTime data, MakeKeyGrbit grbit) { Api.MakeKey(sesid, tableid, data.ToOADate(), 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. /// </summary> /// <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> /// <returns>The data retrieved from the column. Null if the column is null.</returns> public static byte[] RetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid) { return(RetrieveColumn(sesid, tableid, columnid, RetrieveColumnGrbit.None, null)); }
/// <summary> /// Initializes a new instance of the <see cref="TableNameEnumerator"/> class. /// </summary> /// <param name="sesid"> /// The session to use. /// </param> /// <param name="dbid"> /// The database to get the table names from. /// </param> public TableNameEnumerator(JET_SESID sesid, JET_DBID dbid) : base(sesid) { this.dbid = dbid; }
/// <summary> /// Retrieves a string column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// </summary> /// <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="encoding">The string encoding to use when converting data.</param> /// <returns>The data retrieved from the column as a string. Null if the column is null.</returns> public static string RetrieveColumnAsString( JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, Encoding encoding) { return(RetrieveColumnAsString(sesid, tableid, columnid, encoding, RetrieveColumnGrbit.None)); }
/// <summary> /// Try to move to the previous record in the table. If there is not a previous 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 TryMovePrevious(JET_SESID sesid, JET_TABLEID tableid) { return(TryMove(sesid, tableid, JET_Move.Previous, MoveGrbit.None)); }
/// <summary> /// Retrieves a string column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// </summary> /// <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="encoding">The string encoding to use when converting data.</param> /// <param name="grbit">Retrieval options.</param> /// <returns>The data retrieved from the column as a string. Null if the column is null.</returns> public static string RetrieveColumnAsString( JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, Encoding encoding, RetrieveColumnGrbit grbit) { JET_wrn wrn; // This is an optimization for retrieving small Unicode strings // We use a stack-allocated buffer to retrieve the data and then create // a string from the data if (Encoding.Unicode == encoding) { unsafe { // 512 bytes give 256 Unicode characters. const int BufferSize = 512; char * buffer = stackalloc char[BufferSize]; int actualDataSize; wrn = JetRetrieveColumn( sesid, tableid, columnid, new IntPtr(buffer), BufferSize, out actualDataSize, grbit, null); if (JET_wrn.ColumnNull == wrn) { return(null); } if (JET_wrn.Success == wrn) { return(new string(buffer, 0, actualDataSize / sizeof(char))); } Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning code"); // Fallthrough to normal case below } } // Retrieving a string happens in two stages: first the data is retrieved into a data // buffer and then the buffer is converted to a string. The buffer isn't needed for // very long so we try to use a cached buffer. byte[] cachedBuffer = memoryCache.Allocate(); byte[] data = cachedBuffer; int dataSize; wrn = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null); if (JET_wrn.ColumnNull == wrn) { return(null); } if (JET_wrn.BufferTruncated == wrn) { Debug.Assert(dataSize > data.Length, "Expected column to be bigger than buffer"); data = new byte[dataSize]; wrn = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null); if (JET_wrn.BufferTruncated == wrn) { string error = String.Format( CultureInfo.CurrentCulture, "Column size changed from {0} to {1}. The record was probably updated by another thread.", data.Length, dataSize); Trace.TraceError(error); throw new InvalidOperationException(error); } } // TODO: for Unicode strings pin the buffer and use the String(char*) constructor. string s = encoding.GetString(data, 0, dataSize); // Now we have extracted the string from the buffer we can free (cache) the buffer. memoryCache.Free(cachedBuffer); return(s); }
/// <summary> /// Position the cursor after the last record in the table. A /// subsequent move previous will position the cursor on the /// last record. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to position.</param> public static void MoveAfterLast(JET_SESID sesid, JET_TABLEID tableid) { Api.TryMoveLast(sesid, tableid); Api.TryMoveNext(sesid, tableid); }
/// <summary> /// Retrieves a boolean column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// </summary> /// <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> /// <returns>The data retrieved from the column as a boolean. Null if the column is null.</returns> public static bool?RetrieveColumnAsBoolean(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid) { return(RetrieveColumnAsBoolean(sesid, tableid, columnid, RetrieveColumnGrbit.None)); }
/// <summary> /// Recursive SetColumns method for data pinning. This populates the buffer and /// calls the inherited SetColumns method. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid"> /// The table to set the columns in. An update should be prepared. /// </param> /// <param name="columnValues"> /// Column values to set. /// </param> /// <param name="nativeColumns"> /// Structures to put the pinned data in. /// </param> /// <param name="i">Offset of this object in the array.</param> /// <returns>An error code.</returns> internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN *nativeColumns, int i) { var data = this.Value.GetValueOrDefault(); return(this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(byte), this.Value.HasValue)); }
/// <summary> /// Initialize a new ESENT session. /// </summary> /// <param name="instance">The initialized instance to create the session in.</param> /// <param name="sesid">Returns the created session.</param> public static void BeginSession(JET_INSTANCE instance, out JET_SESID sesid) { Api.JetBeginSession(instance, out sesid, null, null); }