public static ulong?RetrieveColumnAsUInt64( JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit) { unsafe { const int DataSize = sizeof(ulong); ulong data; var pointer = new IntPtr(&data); int actualDataSize; JET_wrn wrn = JetRetrieveColumn( sesid, tableid, columnid, pointer, DataSize, out actualDataSize, grbit, null); return(CreateReturnValue(data, DataSize, wrn, actualDataSize)); } }
/// <summary> /// Sets the fields of the object from a native JET_INDEXLIST struct. /// </summary> /// <param name="value"> /// The native indexlist to set the values from. /// </param> internal void SetFromNativeIndexlist(NATIVE_INDEXLIST value) { this.tableid = new JET_TABLEID { Value = value.tableid }; this.cRecord = checked ((int)value.cRecord); this.columnidindexname = new JET_COLUMNID { Value = value.columnidindexname }; this.columnidgrbitIndex = new JET_COLUMNID { Value = value.columnidgrbitIndex }; this.columnidcKey = new JET_COLUMNID { Value = value.columnidcKey }; this.columnidcEntry = new JET_COLUMNID { Value = value.columnidcEntry }; this.columnidcPage = new JET_COLUMNID { Value = value.columnidcPage }; this.columnidcColumn = new JET_COLUMNID { Value = value.columnidcColumn }; this.columnidiColumn = new JET_COLUMNID { Value = value.columnidiColumn }; this.columnidcolumnid = new JET_COLUMNID { Value = value.columnidcolumnid }; this.columnidcoltyp = new JET_COLUMNID { Value = value.columnidcoltyp }; this.columnidLangid = new JET_COLUMNID { Value = value.columnidLangid }; this.columnidCp = new JET_COLUMNID { Value = value.columnidCp }; this.columnidgrbitColumn = new JET_COLUMNID { Value = value.columnidgrbitColumn }; this.columnidcolumnname = new JET_COLUMNID { Value = value.columnidcolumnname }; this.columnidLCMapFlags = new JET_COLUMNID { Value = value.columnidLCMapFlags }; }
/// <summary> /// Creates a dictionary which maps column names to their column IDs. /// </summary> /// <param name="sesid">The sesid to use.</param> /// <param name="tableid">The table to retrieve the information for.</param> /// <returns>A dictionary mapping column names to column IDs.</returns> public static IDictionary <string, JET_COLUMNID> GetColumnDictionary(JET_SESID sesid, JET_TABLEID tableid) { JET_COLUMNLIST columnlist; JetGetTableColumnInfo(sesid, tableid, string.Empty, out columnlist); // As of Sep 2015, JetGetColumnInfoW is only called for Win8+. Even though Unicode should have // worked in Win7, it wasn't reliable until Win8. Encoding encodingOfTextColumns = EsentVersion.SupportsWindows8Features ? Encoding.Unicode : LibraryHelpers.EncodingASCII; try { // esent treats column names as case-insensitive, so we want the dictionary to be case insensitive as well var dict = new Dictionary <string, JET_COLUMNID>( columnlist.cRecord, StringComparer.OrdinalIgnoreCase); if (columnlist.cRecord > 0) { if (Api.TryMoveFirst(sesid, columnlist.tableid)) { do { string name = RetrieveColumnAsString( sesid, columnlist.tableid, columnlist.columnidcolumnname, encodingOfTextColumns, RetrieveColumnGrbit.None); name = StringCache.TryToIntern(name); var columnidValue = (uint)RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid); var columnid = new JET_COLUMNID { Value = columnidValue }; dict.Add(name, columnid); }while (TryMoveNext(sesid, columnlist.tableid)); } } return(dict); } finally { // Close the temporary table used to return the results JetCloseTable(sesid, columnlist.tableid); } }
/// <summary> /// Initializes a new instance of the ColumnInfo class. /// </summary> /// <param name="name">Name of the column.</param> /// <param name="columnid">ID of the column.</param> /// <param name="coltyp">Type of the column.</param> /// <param name="cp">Codepage of the column.</param> /// <param name="maxLength">Maximum length of the column.</param> /// <param name="defaultValue">Column default value.</param> /// <param name="grbit">Column option.</param> internal ColumnInfo( string name, JET_COLUMNID columnid, JET_coltyp coltyp, JET_CP cp, int maxLength, byte[] defaultValue, ColumndefGrbit grbit) { this.Name = name; this.Columnid = columnid; this.Coltyp = coltyp; this.Cp = cp; this.MaxLength = maxLength; this.defaultValue = (null == defaultValue) ? null : Array.AsReadOnly(defaultValue); this.Grbit = grbit; }
/// <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> /// <param name="itagSequence"> /// The sequence number of value in a multi-valued column. /// The array of values is one-based. The first value is /// sequence 1, not 0. If the record column has only one value then /// 1 should be passed as the itagSequence. /// </param> /// <param name="grbit">Retrieve column options.</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, int itagSequence, RetrieveColumnGrbit grbit) { var retinfo = new JET_RETINFO { itagSequence = itagSequence }; int dataSize; JET_wrn wrn = JetRetrieveColumn( sesid, tableid, columnid, null, 0, out dataSize, grbit, retinfo); if (JET_wrn.ColumnNull == wrn) { return(null); } return(dataSize); }
/// <summary> /// Retrieves a single column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// Alternatively, this function can retrieve a column from a record being created /// in the cursor copy buffer. This function can also retrieve column data from an /// index entry that references the current record. In addition to retrieving the /// actual column value, JetRetrieveColumn can also be used to retrieve the size /// of a column, before retrieving the column data itself so that application /// buffers can be sized appropriately. /// </summary> /// <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="grbit">Retrieve column options.</param> /// <param name="retinfo"> /// If pretinfo is give as NULL then the function behaves as though an itagSequence /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to /// retrieve the first value of a multi-valued column, and to retrieve long data at /// offset 0 (zero). /// </param> /// <returns>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, RetrieveColumnGrbit grbit, JET_RETINFO retinfo) { // We expect most column values retrieved this way to be small (retrieving a 1GB LV as one // chunk is a bit extreme!). Allocate a cached buffer and use that, allocating a larger one // if needed. byte[] cache = Caches.ColumnCache.Allocate(); byte[] data = cache; int dataSize; JET_wrn wrn = JetRetrieveColumn( sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo); if (JET_wrn.ColumnNull == wrn) { // null column data = null; } else if (JET_wrn.Success == wrn) { data = MemoryCache.Duplicate(data, dataSize); } else { // there is more data to retrieve Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning", wrn.ToString()); data = new byte[dataSize]; wrn = JetRetrieveColumn( sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo); if (JET_wrn.Success != 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); } } Caches.ColumnCache.Free(ref cache); return(data); }
/// <summary> /// Creates a dictionary which maps column names to their column IDs. /// </summary> /// <param name="sesid">The sesid to use.</param> /// <param name="tableid">The table to retrieve the information for.</param> /// <returns>A dictionary mapping column names to column IDs.</returns> public static IDictionary <string, JET_COLUMNID> GetColumnDictionary(JET_SESID sesid, JET_TABLEID tableid) { JET_COLUMNLIST columnlist; JetGetTableColumnInfo(sesid, tableid, string.Empty, out columnlist); try { // esent treats column names as case-insensitive, so we want the dictionary to be case insensitive as well var dict = new Dictionary <string, JET_COLUMNID>( columnlist.cRecord, StringComparer.OrdinalIgnoreCase); if (columnlist.cRecord > 0) { if (Api.TryMoveFirst(sesid, columnlist.tableid)) { do { string name = RetrieveColumnAsString( sesid, columnlist.tableid, columnlist.columnidcolumnname, NativeMethods.Encoding, RetrieveColumnGrbit.None); name = StringCache.TryToIntern(name); var columnidValue = (uint)RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid); var columnid = new JET_COLUMNID { Value = columnidValue }; dict.Add(name, columnid); }while (TryMoveNext(sesid, columnlist.tableid)); } } return(dict); } finally { // Close the temporary table used to return the results JetCloseTable(sesid, columnlist.tableid); } }
/// <summary> /// Perform atomic addition on one column. The column must be of type /// <see cref="JET_coltyp.Long"/>. This function allows multiple sessions to update the /// same record concurrently without conflicts. /// </summary> /// <remarks> /// This method wraps <see cref="JetEscrowUpdate"/>. /// </remarks> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to update.</param> /// <param name="columnid">The column to update. This must be an escrow-updatable column.</param> /// <param name="delta">The delta to apply to the column.</param> /// <returns>The current value of the column as stored in the database (versioning is ignored).</returns> public static int EscrowUpdate(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, int delta) { var previousValue = new byte[sizeof(int)]; int actualPreviousValueLength; JetEscrowUpdate( sesid, tableid, columnid, BitConverter.GetBytes(delta), sizeof(int), previousValue, previousValue.Length, out actualPreviousValueLength, EscrowUpdateGrbit.None); Debug.Assert( previousValue.Length == actualPreviousValueLength, "Unexpected previous value length. Expected an Int32"); return(BitConverter.ToInt32(previousValue, 0)); }
/// <summary> /// Retrieves a single column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// Alternatively, this function can retrieve a column from a record being created /// in the cursor copy buffer. This function can also retrieve column data from an /// index entry that references the current record. In addition to retrieving the /// actual column value, JetRetrieveColumn can also be used to retrieve the size /// of a column, before retrieving the column data itself so that application /// buffers can be sized appropriately. /// </summary> /// <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="grbit">Retrieve column options.</param> /// <param name="retinfo"> /// If pretinfo is give as NULL then the function behaves as though an itagSequence /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to /// retrieve the first value of a multi-valued column, and to retrieve long data at /// offset 0 (zero). /// </param> /// <returns>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, RetrieveColumnGrbit grbit, JET_RETINFO retinfo) { // We expect most column values retrieved this way to be small (retrieving a 1GB LV as one // chunk is a bit extreme!). Allocate a small buffer and use that, allocating a larger one // if needed. var data = new byte[256]; int dataSize; JET_wrn wrn = JetRetrieveColumn( sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo); if (JET_wrn.ColumnNull == wrn) { // null column data = null; } else { Array.Resize(ref data, dataSize); if (JET_wrn.BufferTruncated == wrn) { // there is more data to retrieve wrn = JetRetrieveColumn( sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo); if (JET_wrn.Success != 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); } } } return(data); }
/// <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 { byte[] bytes = encoding.GetBytes(data); JetSetColumn(sesid, tableid, columnid, bytes, bytes.Length, grbit, null); } }
/// <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 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> /// 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> /// 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> /// 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> /// Write a serialized form of an object to a column. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to write to. An update should be prepared.</param> /// <param name="columnid">The column to write to.</param> /// <param name="value">The object to write. The object must be serializable.</param> public static void SerializeObjectToColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, object value) { if (null == value) { Api.SetColumn(sesid, tableid, columnid, null); } else { using (var stream = new ColumnStream(sesid, tableid, columnid)) { var serializer = new BinaryFormatter { Context = new StreamingContext(StreamingContextStates.Persistence) }; serializer.Serialize(stream, value); } } }
/// <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> /// Retrieve a Unicode (UTF16) string. This is optimized to take advantage of the fact /// that no conversion is needed. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to retrieve from.</param> /// <param name="columnid">The column to retrieve.</param> /// <param name="grbit">Retrieve options.</param> /// <returns>The string retrieved from the column.</returns> private static unsafe string RetrieveUnicodeString(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit) { // 512 Unicode characters (1kb on stack) const int BufferSize = 512; char * buffer = stackalloc char[BufferSize]; int actualDataSize; JET_wrn wrn = JetRetrieveColumn(sesid, tableid, columnid, new IntPtr(buffer), BufferSize * sizeof(char), out actualDataSize, grbit, null); if (JET_wrn.ColumnNull == wrn) { return(null); } if (JET_wrn.Success == wrn) { ////return StringCache.GetString(buffer, 0, actualDataSize); return(new string(buffer, 0, actualDataSize / sizeof(char))); } Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning code"); // Create a fake string of the appropriate size and then fill it in. var s = new string('\0', actualDataSize / sizeof(char)); fixed(char *p = s) { int newDataSize; wrn = JetRetrieveColumn(sesid, tableid, columnid, new IntPtr(p), actualDataSize, out newDataSize, 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.", actualDataSize, newDataSize); Trace.TraceError(error); throw new InvalidOperationException(error); } } return(s); }
/// <summary> /// Retrieves a single column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// Alternatively, this function can retrieve a column from a record being created /// in the cursor copy buffer. This function can also retrieve column data from an /// index entry that references the current record. In addition to retrieving the /// actual column value, JetRetrieveColumn can also be used to retrieve the size /// of a column, before retrieving the column data itself so that application /// buffers can be sized appropriately. /// </summary> /// <remarks> /// This is an internal-use version that takes an IntPtr. /// </remarks> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to retrieve the column from.</param> /// <param name="columnid">The columnid to retrieve.</param> /// <param name="data">The data buffer to be retrieved into.</param> /// <param name="dataSize">The size of the data buffer.</param> /// <param name="actualDataSize">Returns the actual size of the data buffer.</param> /// <param name="grbit">Retrieve column options.</param> /// <param name="retinfo"> /// If pretinfo is give as NULL then the function behaves as though an itagSequence /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to /// retrieve the first value of a multi-valued column, and to retrieve long data at /// offset 0 (zero). /// </param> /// <returns>An ESENT warning code.</returns> internal static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo) { return(Api.Check(Impl.JetRetrieveColumn(sesid, tableid, columnid, data, dataSize, out actualDataSize, grbit, retinfo))); }
/// <summary> /// 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> /// 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> /// 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)); }
public static ulong?RetrieveColumnAsUInt64(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid) { return(RetrieveColumnAsUInt64(sesid, tableid, columnid, RetrieveColumnGrbit.None)); }
/// <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> public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data) { SetColumn(sesid, tableid, columnid, data, SetColumnGrbit.None); }
/// <summary> /// The JetSetColumn function modifies a single column value in a modified record to be inserted or to /// update the current record. It can overwrite an existing value, add a new value to a sequence of /// values in a multi-valued column, remove a value from a sequence of values in a multi-valued column, /// or update all or part of a long value, a column of type JET_coltyp.LongText or JET_coltyp.LongBinary. /// </summary> /// <remarks> /// This method takes an IntPtr and is intended for internal use only. /// </remarks> /// <param name="sesid">The session which is performing the update.</param> /// <param name="tableid">The cursor to update. An update should be prepared.</param> /// <param name="columnid">The columnid to set.</param> /// <param name="data">The data to set.</param> /// <param name="dataSize">The size of data to set.</param> /// <param name="grbit">SetColumn options.</param> /// <param name="setinfo">Used to specify itag or long-value offset.</param> /// <returns>A warning value.</returns> internal static JET_wrn JetSetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, SetColumnGrbit grbit, JET_SETINFO setinfo) { return(Api.Check(Impl.JetSetColumn(sesid, tableid, columnid, data, dataSize, grbit, setinfo))); }
/// <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> /// Retrieves a single column value from the current record. The record is that /// record associated with the index entry at the current position of the cursor. /// Alternatively, this function can retrieve a column from a record being created /// in the cursor copy buffer. This function can also retrieve column data from an /// index entry that references the current record. In addition to retrieving the /// actual column value, JetRetrieveColumn can also be used to retrieve the size /// of a column, before retrieving the column data itself so that application /// buffers can be sized appropriately. /// </summary> /// <remarks> /// This is an internal method that takes a buffer offset as well as size. /// </remarks> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The cursor to retrieve the column from.</param> /// <param name="columnid">The columnid to retrieve.</param> /// <param name="data">The data buffer to be retrieved into.</param> /// <param name="dataSize">The size of the data buffer.</param> /// <param name="dataOffset">Offset into the data buffer to read data into.</param> /// <param name="actualDataSize">Returns the actual size of the data buffer.</param> /// <param name="grbit">Retrieve column options.</param> /// <param name="retinfo"> /// If pretinfo is give as NULL then the function behaves as though an itagSequence /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to /// retrieve the first value of a multi-valued column, and to retrieve long data at /// offset 0 (zero). /// </param> /// <returns>An ESENT warning code.</returns> public static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, int dataOffset, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo) { if (dataOffset < 0 || (null != data && 0 != dataSize && dataOffset >= data.Length) || (null == data && dataOffset != 0)) { throw new ArgumentOutOfRangeException( "dataOffset", dataOffset, "must be inside the data buffer"); } if ((null == data && dataSize > 0) || (null != data && dataSize > data.Length)) { throw new ArgumentOutOfRangeException( "dataSize", dataSize, "cannot be greater than the length of the data"); } unsafe { fixed(byte *pointer = data) { return(Api.JetRetrieveColumn( sesid, tableid, columnid, new IntPtr(pointer + dataOffset), dataSize, out actualDataSize, grbit, retinfo)); } } }
/// <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> /// <param name="grbit">The retrieval options to use.</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, RetrieveColumnGrbit grbit) { int actualSize; if (JET_wrn.ColumnNull == Api.JetRetrieveColumn(sesid, tableid, columnid, null, 0, out actualSize, grbit, null)) { return(null); } using (var stream = new ColumnStream(sesid, tableid, columnid)) { var deseriaizer = new BinaryFormatter(); return(deseriaizer.Deserialize(stream)); } }
/// <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)); }