/// <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); } } }
public void ConvertSetinfoToNative() { var setinfo = new JET_SETINFO { ibLongValue = 1, itagSequence = 2 }; NATIVE_SETINFO native = setinfo.GetNativeSetinfo(); Assert.AreEqual(1U, native.ibLongValue); Assert.AreEqual(2U, native.itagSequence); }
/// <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); } }
/// <summary> /// Writes a sequence of bytes to the current stream and advances the current /// position within this stream by the number of bytes written. /// </summary> /// <param name="buffer">The buffer to write from.</param> /// <param name="offset">The offset in the buffer to write.</param> /// <param name="count">The number of bytes to write.</param> public override void Write(byte[] buffer, int offset, int count) { CheckBufferArguments(buffer, offset, count); int length = checked ((int)this.Length); JET_SETINFO setinfo; int newIbLongValue = checked (this.ibLongValue + count); // If our current position is beyond the end of the LV extend // the LV to the write point if (this.ibLongValue > length) { setinfo = new JET_SETINFO { itagSequence = this.Itag }; Api.JetSetColumn(this.sesid, this.tableid, this.columnid, null, this.ibLongValue, SetColumnGrbit.SizeLV, setinfo); length = this.ibLongValue; } SetColumnGrbit grbit; if (this.ibLongValue == length) { grbit = SetColumnGrbit.AppendLV; } else if (newIbLongValue >= length) { grbit = SetColumnGrbit.OverwriteLV | SetColumnGrbit.SizeLV; } else { grbit = SetColumnGrbit.OverwriteLV; } setinfo = new JET_SETINFO { itagSequence = this.Itag, ibLongValue = this.ibLongValue }; Api.JetSetColumn(this.sesid, this.tableid, this.columnid, buffer, count, offset, grbit, setinfo); checked { this.ibLongValue += count; } }
/// <summary> /// Writes a sequence of bytes to the current stream and advances the current /// position within this stream by the number of bytes written. /// </summary> /// <param name="buffer">The buffer to write from.</param> /// <param name="offset">The offset in the buffer to write.</param> /// <param name="count">The number of bytes to write.</param> public override void Write(byte[] buffer, int offset, int count) { CheckBufferArguments(buffer, offset, count); int length = checked((int)this.Length); JET_SETINFO setinfo; int newIbLongValue = checked(this.ibLongValue + count); // If our current position is beyond the end of the LV extend // the LV to the write point if (this.ibLongValue > length) { setinfo = new JET_SETINFO { itagSequence = this.Itag }; Api.JetSetColumn(this.sesid, this.tableid, this.columnid, null, this.ibLongValue, SetColumnGrbit.SizeLV, setinfo); length = this.ibLongValue; } SetColumnGrbit grbit; if (this.ibLongValue == length) { grbit = SetColumnGrbit.AppendLV; } else if (newIbLongValue >= length) { grbit = SetColumnGrbit.OverwriteLV | SetColumnGrbit.SizeLV; } else { grbit = SetColumnGrbit.OverwriteLV; } setinfo = new JET_SETINFO { itagSequence = this.Itag, ibLongValue = this.ibLongValue }; Api.JetSetColumn(this.sesid, this.tableid, this.columnid, buffer, count, offset, grbit, setinfo); checked { this.ibLongValue += count; } }
/// <summary> /// Updates a record setting the given column set to the specified value. /// </summary> /// <param name="columnid">The column to set.</param> /// <param name="data">The data to set.</param> /// <param name="itagSequence">The itag sequence to set.</param> private void SetColumn(JET_COLUMNID columnid, byte[] data, int itagSequence) { var setinfo = new JET_SETINFO { ibLongValue = 0, itagSequence = itagSequence, }; Api.JetSetColumn(this.sesid, this.tableid, columnid, data, (null == data) ? 0 : data.Length, SetColumnGrbit.None, setinfo); }
public void HowDoIDealWithMultivalues() { JET_SESID sesid = this.testSession; JET_DBID dbid = this.testDbid; JET_TABLEID tableid; JET_COLUMNDEF columndef = new JET_COLUMNDEF(); JET_COLUMNID tagColumn; Api.JetCreateTable(sesid, dbid, "table", 0, 100, out tableid); // Create the column. Any column can be multivalued. Using // ColumndefGrbit controls how the column is indexed. columndef.coltyp = JET_coltyp.LongText; columndef.cp = JET_CP.Unicode; columndef.grbit = ColumndefGrbit.ColumnMultiValued; Api.JetAddColumn(sesid, tableid, "tags", columndef, null, 0, out tagColumn); // Create the index. There will be one entry in the index for each // instance of the multivalued column. const string IndexKey = "+tags\0\0"; Api.JetCreateIndex(sesid, tableid, "tagsindex", CreateIndexGrbit.None, IndexKey, IndexKey.Length, 100); Api.JetBeginTransaction(sesid); // Now insert a record. An ESENT column can have multiple instances (multivalues) // inside the same record. Each multivalue is identified by an itag, the first itag // in a sequence is 1. Api.JetPrepareUpdate(sesid, tableid, JET_prep.Insert); // With no JET_SETINFO specified, itag 1 will be set. byte[] data = Encoding.Unicode.GetBytes("foo"); Api.JetSetColumn(sesid, tableid, tagColumn, data, data.Length, SetColumnGrbit.None, null); // Set a column with a setinfo. The itagSequence in the setinfo will be 0, which // means the value will be added to the collection of values, i.e. the column will // have two instances, "foo" and "bar". JET_SETINFO setinfo = new JET_SETINFO(); data = Encoding.Unicode.GetBytes("bar"); Api.JetSetColumn(sesid, tableid, tagColumn, data, data.Length, SetColumnGrbit.None, setinfo); // Add a third instance, explicitly setting the itagSequence data = Encoding.Unicode.GetBytes("baz"); setinfo.itagSequence = 4; Api.JetSetColumn(sesid, tableid, tagColumn, data, data.Length, SetColumnGrbit.None, setinfo); // Add a duplicate value, checking for uniqueness data = Encoding.Unicode.GetBytes("foo"); setinfo.itagSequence = 0; try { Api.JetSetColumn(sesid, tableid, tagColumn, data, data.Length, SetColumnGrbit.UniqueMultiValues, setinfo); Assert.Fail("Expected an EsentErrorException"); } catch (EsentErrorException ex) { Assert.AreEqual(JET_err.MultiValuedDuplicate, ex.Error); } Api.JetUpdate(sesid, tableid); // Find the record. We can seek for any column instance. Api.JetSetCurrentIndex(sesid, tableid, "tagsindex"); Api.MakeKey(sesid, tableid, "bar", Encoding.Unicode, MakeKeyGrbit.NewKey); Assert.IsTrue(Api.TrySeek(sesid, tableid, SeekGrbit.SeekEQ)); // Retrieve the number of column instances. This can be done with JetRetrieveColumns by setting // itagSequence to 0. JET_RETRIEVECOLUMN retrievecolumn = new JET_RETRIEVECOLUMN(); retrievecolumn.columnid = tagColumn; retrievecolumn.itagSequence = 0; Api.JetRetrieveColumns(sesid, tableid, new[] { retrievecolumn }, 1); Console.WriteLine("{0}", retrievecolumn.itagSequence); Assert.AreEqual(3, retrievecolumn.itagSequence); // Retrieve all the columns for (int itag = 1; itag <= retrievecolumn.itagSequence; ++itag) { JET_RETINFO retinfo = new JET_RETINFO { itagSequence = itag }; string s = Encoding.Unicode.GetString(Api.RetrieveColumn(sesid, tableid, tagColumn, RetrieveColumnGrbit.None, retinfo)); Console.WriteLine("{0}: {1}", itag, s); } // Update the record Api.JetPrepareUpdate(sesid, tableid, JET_prep.Replace); // With no JET_SETINFO specified, itag 1 will be set, overwriting the existing value. data = Encoding.Unicode.GetBytes("qux"); Api.JetSetColumn(sesid, tableid, tagColumn, data, data.Length, SetColumnGrbit.None, null); // Set an instance to null to delete it. setinfo.itagSequence = 2; Api.JetSetColumn(sesid, tableid, tagColumn, null, 0, SetColumnGrbit.None, setinfo); // Removing itag 2 moved the other itags down (i.e. itag 3 became itag 2). // Overwrite itag 2. data = Encoding.Unicode.GetBytes("xyzzy"); setinfo.itagSequence = 2; Api.JetSetColumn(sesid, tableid, tagColumn, data, data.Length, SetColumnGrbit.None, setinfo); // Now add a new instance by setting itag 0. This instance will go at the end. data = Encoding.Unicode.GetBytes("flob"); setinfo.itagSequence = 0; Api.JetSetColumn(sesid, tableid, tagColumn, data, data.Length, SetColumnGrbit.None, setinfo); Api.JetUpdate(sesid, tableid); // Retrieve the number of column instances again. retrievecolumn.itagSequence = 0; Api.JetRetrieveColumns(sesid, tableid, new[] { retrievecolumn }, 1); // Retrieve all the columns for (int itag = 1; itag <= retrievecolumn.itagSequence; ++itag) { JET_RETINFO retinfo = new JET_RETINFO { itagSequence = itag }; string s = Encoding.Unicode.GetString(Api.RetrieveColumn(sesid, tableid, tagColumn, RetrieveColumnGrbit.None, retinfo)); Console.WriteLine("{0}: {1}", itag, s); } Api.JetCommitTransaction(sesid, CommitTransactionGrbit.LazyFlush); }
/// <summary> /// Updates a record setting the given column set to the specified value. /// </summary> /// <param name="columnid">The column to set.</param> /// <param name="data">The data to set.</param> /// <param name="itagSequence">The itag sequence to set.</param> private void SetColumn(JET_COLUMNID columnid, byte[] data, int itagSequence) { Api.JetBeginTransaction(this.sesid); Api.JetPrepareUpdate(this.sesid, this.tableid, JET_prep.Replace); var setinfo = new JET_SETINFO { ibLongValue = 0, itagSequence = itagSequence, }; Api.JetSetColumn(this.sesid, this.tableid, columnid, data, (null == data) ? 0 : data.Length, SetColumnGrbit.None, setinfo); Api.JetUpdate(this.sesid, this.tableid); Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush); }
public void ConvertSetinfoToNativeWhenItagSequenceIsNegative() { var setinfo = new JET_SETINFO { ibLongValue = 0, itagSequence = Int32.MinValue }; NATIVE_SETINFO native = setinfo.GetNativeSetinfo(); }
/// <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 <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); }
// insert a record and update its long-values private void UpdateLongValues() { Console.WriteLine("\tUpdate Long-Values"); JET_TABLEID tableid; Api.JetOpenTable(this.sesid, this.dbid, this.table, null, 0, OpenTableGrbit.None, out tableid); int recordID = NumRecords + 17; var rand = new Random(recordID); var data = new byte[this.columnInfos.Length][]; Api.JetBeginTransaction(this.sesid); // insert the record using (var update = new Update(this.sesid, tableid, JET_prep.Insert)) { for (int i = 0; i < this.columnInfos.Length; ++i) { data[i] = null; if (String.Equals( this.columnInfos[i].Name, "recordID", StringComparison.InvariantCultureIgnoreCase)) { // this is the primary index column, set it to the recordID data[i] = BitConverter.GetBytes(recordID); } else if (this.columnInfos[i].Coltyp == JET_coltyp.LongBinary || this.columnInfos[i].Coltyp == JET_coltyp.LongText) { data[i] = DataGenerator.GetRandomColumnData( this.columnInfos[i].Coltyp, this.columnInfos[i].Cp, rand); } if (null != data[i]) { Api.SetColumn(this.sesid, tableid, this.columnInfos[i].Columnid, data[i]); } } update.SaveAndGotoBookmark(); } this.CheckColumns(this.sesid, tableid, data); // update the record using (var update = new Update(this.sesid, tableid, JET_prep.Replace)) { for (int i = 0; i < this.columnInfos.Length; ++i) { if (this.columnInfos[i].Coltyp == JET_coltyp.LongBinary || this.columnInfos[i].Coltyp == JET_coltyp.LongText) { int size = Api.RetrieveColumnSize(this.sesid, tableid, this.columnInfos[i].Columnid).Value; BasicClass.Assert(size == data[i].Length, "Invalid column size"); var setinfo = new JET_SETINFO(); setinfo.ibLongValue = size / 2; setinfo.itagSequence = 1; // the data that will be added to the column byte[] newdata = DataGenerator.GetRandomColumnData( this.columnInfos[i].Coltyp, this.columnInfos[i].Cp, rand); // what the final data should be byte[] finaldata = null; switch (rand.Next(2)) { case 0: // append Api.SetColumn( this.sesid, tableid, this.columnInfos[i].Columnid, newdata, SetColumnGrbit.AppendLV); finaldata = new byte[size + newdata.Length]; Array.Copy(data[i], finaldata, size); Array.Copy(newdata, 0, finaldata, size, newdata.Length); break; case 1: // overwrite and set size Api.JetSetColumn( this.sesid, tableid, this.columnInfos[i].Columnid, newdata, newdata.Length, SetColumnGrbit.SizeLV | SetColumnGrbit.OverwriteLV, setinfo); finaldata = new byte[setinfo.ibLongValue + newdata.Length]; Array.Copy(data[i], finaldata, setinfo.ibLongValue); Array.Copy(newdata, 0, finaldata, setinfo.ibLongValue, newdata.Length); break; } data[i] = finaldata; } } update.SaveAndGotoBookmark(); } this.CheckColumns(this.sesid, tableid, data); Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush); Api.JetCloseTable(this.sesid, tableid); }
public void JetSetColumnThrowsExceptionWhenIbLongValueIsNegative() { var setinfo = new JET_SETINFO { ibLongValue = -1 }; Api.JetSetColumn(this.sesid, this.tableid, this.columnid, null, 0, SetColumnGrbit.None, setinfo); }
public void JetSetinfoToString() { var value = new JET_SETINFO { ibLongValue = 1, itagSequence = 2 }; Assert.AreEqual("JET_SETINFO(ibLongValue=1,itagSequence=2)", value.ToString()); }
/// <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); } }
/// <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 <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> /// Insert a record with the given column values. After the insert the cursor is /// positioned on the record. /// </summary> /// <param name="key"> /// The key of the record. /// </param> /// <param name="values"> /// The column values to insert. /// </param> private void InsertRecord(int key, params string[] values) { using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) { Api.SetColumn(this.sesid, this.tableid, this.keyColumn, key); foreach (string value in values) { var setinfo = new JET_SETINFO { ibLongValue = 0, itagSequence = 0, }; byte[] data = Encoding.Unicode.GetBytes(value); Api.JetSetColumn( this.sesid, this.tableid, this.multiValueColumn, data, data.Length, SetColumnGrbit.None, setinfo); } update.SaveAndGotoBookmark(); transaction.Commit(CommitTransactionGrbit.None); } }
/// <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++; } }