/// <summary> /// Sets the column. /// </summary> /// <param name="columnid">The columnid.</param> /// <param name="coltyp">The coltyp.</param> /// <param name="isAscii">Whether a textual column is Ascii.</param> /// <param name="index">The index.</param> /// <param name="obj">The object.</param> /// <exception cref="System.InvalidOperationException">You may only update fields through Cursor.EditRecord.</exception> /// <remarks> /// Itags start at 1, so we add 1 to the index /// </remarks> private void SetColumn(JET_COLUMNID columnid, JET_coltyp coltyp, bool isAscii, int index, object obj) { lock (this.isamSession) { this.cursor.CheckDisposed(); if ((this.grbit & RetrieveColumnGrbit.RetrieveCopy) == 0) { this.cursor.CheckRecord(); throw new InvalidOperationException("You may only update fields through Cursor.EditRecord."); } // if this is a Sort or PreSortTemporary TT and we are setting // an LV column then always attempt to use intrinsic LVs SetColumnGrbit grbitSet = SetColumnGrbit.None; if ((this.cursor.TableDefinition.Type == TableType.Sort || this.cursor.TableDefinition.Type == TableType.PreSortTemporary) && (coltyp == JET_coltyp.LongText || coltyp == JET_coltyp.LongBinary)) { grbitSet = grbitSet | SetColumnGrbit.IntrinsicLV; } JET_SETINFO setinfo = new JET_SETINFO(); setinfo.ibLongValue = 0; setinfo.itagSequence = index + 1; byte[] bytes = Converter.BytesFromObject(coltyp, isAscii, obj); int bytesLength = bytes == null ? 0 : bytes.Length; Api.JetSetColumn(this.isamSession.Sesid, this.tableid, columnid, bytes, bytesLength, grbitSet, setinfo); this.updateID++; } }
/// <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 <see cref="JET_coltyp.LongText"/> /// or <see cref="JET_coltyp.LongBinary"/>). /// </summary> /// <remarks> /// This is an internal-only version of the API that takes a data buffer and an offset into the buffer. /// </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="dataOffset">The offset in the data buffer to set data from.</param> /// <param name="grbit">SetColumn options.</param> /// <param name="setinfo">Used to specify itag or long-value offset.</param> /// <returns>A warning value.</returns> public static JET_wrn JetSetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, int dataOffset, SetColumnGrbit grbit, JET_SETINFO setinfo) { 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 > checked(data.Length - dataOffset) && (SetColumnGrbit.SizeLV != (grbit & SetColumnGrbit.SizeLV))) { throw new ArgumentOutOfRangeException( "dataSize", dataSize, "cannot be greater than the length of the data (unless the SizeLV option is used)"); } unsafe { fixed (byte* pointer = data) { return Api.JetSetColumn(sesid, tableid, columnid, new IntPtr(pointer + dataOffset), 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> public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data) { SetColumnGrbit grbit = ((null != data) && (0 == data.Length)) ? SetColumnGrbit.ZeroLength : SetColumnGrbit.None; int dataLength = (null == data) ? 0 : data.Length; JetSetColumn(sesid, tableid, columnid, data, dataLength, 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> /// <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) { // The encoding output will fix in a cached buffer. Get one to avoid // more memory allocations. byte[] 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); } } Caches.ColumnCache.Free(ref buffer); } else { byte[] bytes = encoding.GetBytes(data); JetSetColumn(sesid, tableid, columnid, bytes, bytes.Length, grbit, null); } }
/// <summary> /// Sets the length of the stream. /// </summary> /// <param name="value">The desired length, in bytes.</param> public override void SetLength(long value) { if (value > MaxLongValueSize || value < 0) { throw new ArgumentOutOfRangeException("value", value, "A LongValueStream cannot be longer than 0x7FFFFFF or less than 0 bytes"); } if (value < this.Length && value > 0) { // BUG: Shrinking the column multiple times and then growing it can sometimes hit an unpleasant // ESENT defect which causes a hang. To make sure we never have that problem we read out the data, // and insert into a new long-value. This is not efficient. var data = new byte[value]; var retinfo = new JET_RETINFO { itagSequence = this.Itag, ibLongValue = 0 }; int actualDataSize; Api.JetRetrieveColumn( this.sesid, this.tableid, this.columnid, data, data.Length, out actualDataSize, RetrieveGrbit, retinfo); var setinfo = new JET_SETINFO { itagSequence = this.Itag }; Api.JetSetColumn(this.sesid, this.tableid, this.columnid, data, data.Length, SetColumnGrbit.None, setinfo); } else { var setinfo = new JET_SETINFO { itagSequence = this.Itag }; SetColumnGrbit grbit = (0 == value) ? SetColumnGrbit.ZeroLength : SetColumnGrbit.SizeLV; Api.JetSetColumn(this.sesid, this.tableid, this.columnid, null, checked ((int)value), grbit, setinfo); } // Setting the length moves the offset back to the end of the data if (this.ibLongValue > value) { this.ibLongValue = checked ((int)value); } }
// set columns in the record (the data array should match the columnInfos array) private void SetColumns(JET_SESID sesid, JET_TABLEID tableid, byte[][] data) { for (int i = 0; i < this.columnInfos.Length; ++i) { // don't overwrite autoinc columns if (!this.IsColumnAutoinc(this.columnInfos[i].Grbit)) { SetColumnGrbit grbit = SetColumnGrbit.None; if (this.IsColumnSeparatedLV(this.columnInfos[i])) { grbit |= SetColumnGrbit.SeparateLV; } Api.SetColumn(sesid, tableid, this.columnInfos[i].Columnid, data[i], grbit); } } }
/// <summary> /// Set a column in a record. An update must be prepared. /// </summary> /// <param name="columnid">The columnid to set.</param> /// <param name="data">The data to set.</param> /// <param name="grbit">Options for JetSetColumn.</param> public virtual void SetColumn(JET_COLUMNID columnid, byte[] data, SetColumnGrbit grbit) { this.Tracer.TraceVerbose("SetColumn"); this.CheckNotDisposed(); this.CheckInUpdate(); if (null == data) { Api.JetSetColumn(this.session, this.table, columnid, null, 0, grbit, null); } else if (data.Length == 0) { Api.JetSetColumn(this.session, this.table, columnid, null, 0, grbit | SetColumnGrbit.ZeroLength, null); } else { Api.JetSetColumn(this.session, this.table, columnid, data, data.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> /// <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, (IntPtr) buffer, data.Length * sizeof(char), grbit, null); } } } else { byte[] bytes = encoding.GetBytes(data); JetSetColumn(sesid, tableid, columnid, bytes, bytes.Length, grbit, null); } }
/// <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 <see cref="JET_coltyp.LongText"/> /// or <see cref="JET_coltyp.LongBinary"/>). /// </summary> /// <remarks> /// This is an internal-only version of the API that takes a data buffer and an offset into the buffer. /// </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="dataOffset">The offset in the data buffer to set data from.</param> /// <param name="grbit">SetColumn options.</param> /// <param name="setinfo">Used to specify itag or long-value offset.</param> /// <returns>A warning value.</returns> public static JET_wrn JetSetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, int dataOffset, SetColumnGrbit grbit, JET_SETINFO setinfo) { 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 > checked (data.Length - dataOffset) && (SetColumnGrbit.SizeLV != (grbit & SetColumnGrbit.SizeLV))) { throw new ArgumentOutOfRangeException( "dataSize", dataSize, "cannot be greater than the length of the data (unless the SizeLV option is used)"); } unsafe { fixed(byte *pointer = data) { return(Api.JetSetColumn(sesid, tableid, columnid, new IntPtr(pointer + dataOffset), dataSize, grbit, setinfo)); } } }
/// <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> /// 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> /// <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> /// 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="grbit">SetColumn options.</param> public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, SetColumnGrbit grbit) { if ((null != data) && (0 == data.Length)) { grbit |= SetColumnGrbit.ZeroLength; } int dataLength = (null == data) ? 0 : data.Length; JetSetColumn(sesid, tableid, columnid, data, dataLength, 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> /// <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) { // The encoding output will fix in a cached buffer. Get one to avoid // more memory allocations. byte[] 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); } } Caches.ColumnCache.Free(ref buffer); } 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> /// <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> /// 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 <see cref="JET_coltyp.LongText"/> /// or <see cref="JET_coltyp.LongBinary"/>). /// </summary> /// <remarks> /// The SetColumn methods provide datatype-specific overrides which may be more efficient. /// </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 code.</returns> public static JET_wrn JetSetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, SetColumnGrbit grbit, JET_SETINFO setinfo) { return Api.JetSetColumn(sesid, tableid, columnid, data, dataSize, 0, 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> /// <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); } }