示例#1
0
        /// <summary>Store the column value in the database.</summary>
        public override void Serialize(EseCursorBase cur, JET_COLUMNID idColumn, object value, bool bNewRecord)
        {
            if (!bNewRecord)
            {
                // If this is an UPDATE operation, erase the old values.
                JET_SETINFO si = new JET_SETINFO();
                for (int itg = GetValuesCountSilent(cur, idColumn); itg > 0; itg--)
                {
                    si.ibLongValue  = 0;
                    si.itagSequence = itg;
                    Api.JetSetColumn(cur.idSession, cur.idTable, idColumn,
                                     null, 0, SetColumnGrbit.None, si);
                }
            }

            var arr = value as int[];

            if (null == arr)
            {
                return;
            }

            // Set new values
            foreach (var s in arr)
            {
                AddValue(cur, idColumn, s);
            }
        }
示例#2
0
        /// <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++;
            }
        }
示例#3
0
        // Append the given value to this column
        void AddValue(EseCursorBase cur, JET_COLUMNID idColumn, int val)
        {
            byte[]      data = BitConverter.GetBytes(val);
            JET_SETINFO si   = new JET_SETINFO();

            si.itagSequence = 0;
            Api.JetSetColumn(cur.idSession, cur.idTable, idColumn, data, data.Length, SetColumnGrbit.None, si);
        }
示例#4
0
        public void ConvertSetinfoToNativeWhenItagSequenceIsNegative()
        {
            var setinfo = new JET_SETINFO {
                ibLongValue = 0, itagSequence = Int32.MinValue
            };

            NATIVE_SETINFO native = setinfo.GetNativeSetinfo();
        }
示例#5
0
        public void VerifySetinfoCanBeSerialized()
        {
            var expected = new JET_SETINFO {
                ibLongValue = 5, itagSequence = 6
            };

            SerializeAndCompareContent(expected);
        }
示例#6
0
        public void JetSetinfoToString()
        {
            var value = new JET_SETINFO {
                ibLongValue = 1, itagSequence = 2
            };

            Assert.AreEqual("JET_SETINFO(ibLongValue=1,itagSequence=2)", value.ToString());
        }
示例#7
0
        /// <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);
        }
示例#8
0
        public void VerifyJetSetinfoEquality()
        {
            var x = new JET_SETINFO {
                ibLongValue = 1, itagSequence = 2
            };
            var y = new JET_SETINFO {
                ibLongValue = 1, itagSequence = 2
            };

            TestContentEquals(x, y);
        }
示例#9
0
        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);
        }
示例#10
0
            public void Clear()
            {
                var si = new JET_SETINFO()
                {
                    itagSequence = 1
                };

                for (var i = 0; i < Count; i++)
                {
                    Api.JetSetColumn(_table.Session, _table.Table, _columnid, null, 0, SetColumnGrbit.None, si);
                }
            }
示例#11
0
        // Put the column value to the ESE.
        void LoadVal(string strVal, JET_COLUMNID idColumn, JET_coltyp ct, JET_CP cp)
        {
            if (String.IsNullOrEmpty(strVal))
            {
                return;
            }

            byte[] val = null;
            if (ct == JET_coltyp.Currency)                                               // int64
            {
                val = BitConverter.GetBytes(Convert.ToUInt64(strVal, 16));
            }
            else if (ct == JET_coltyp.Long)                                              // int32
            {
                val = BitConverter.GetBytes(Convert.ToUInt32(strVal, 16));
            }
            else if (ct == JET_coltyp.Short)                                             // int16
            {
                val = BitConverter.GetBytes(Convert.ToUInt16(strVal, 16));
            }
            else if (ct == JET_coltyp.UnsignedByte)                                      // uint8
            {
                val = new byte[1] {
                    Convert.ToByte(strVal, 16)
                }
            }
            ;
            else if (ct == JET_coltyp.DateTime)                                          // DateTime
            {
                DateTime dt  = DateTime.Parse(strVal, null, System.Globalization.DateTimeStyles.RoundtripKind);
                double   dbl = dt.ToOADate();
                val = BitConverter.GetBytes(dbl);
            }
            else if (ct == JET_coltyp.Text || ct == JET_coltyp.LongText)                 // Text
            {
                if (cp == JET_CP.Unicode)
                {
                    val = TSV.UnescapeUnicode(strVal).ToArray();
                }
                else
                {
                    val = TSV.UnescapeASCII(strVal).ToArray();
                }
            }
            else
            {
                val = Convert.FromBase64String(strVal);                                  // Anything else
            }
            JET_SETINFO si = new JET_SETINFO();

            si.itagSequence = 0;
            Api.JetSetColumn(sess.idSession, idTable, idColumn, val, val.Length, SetColumnGrbit.None, si);
        }
示例#12
0
        protected void ClearMultiValue(EsentTable table, JET_COLUMNID columnid)
        {
            var cnt = GetMultiValueCount(table, columnid);
            var si  = new JET_SETINFO()
            {
                itagSequence = 1
            };

            for (var i = 0; i < cnt; i++)
            {
                Api.JetSetColumn(table.Session, table.Table, columnid, null, 0, SetColumnGrbit.None, si);
            }
        }
示例#13
0
        /// <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 RemoveChannel(string channel)
        {
            Api.JetPrepareUpdate(_sesid, _table, JET_prep.Replace);
            try
            {
                // Get the existing channels
                var column = new JET_RETRIEVECOLUMN
                {
                    columnid = _channelColumn,
                    grbit    = RetrieveColumnGrbit.RetrieveTag
                };

                Api.JetRetrieveColumns(_sesid, _table, new[] { column }, 1);

                int count = column.itagSequence;
                for (int i = 1; i <= count; i++)
                {
                    JET_RETINFO retinfo = new JET_RETINFO {
                        itagSequence = i
                    };
                    byte[] data = Api.RetrieveColumn(_sesid, _table, _channelColumn, RetrieveColumnGrbit.None, retinfo);
                    if (channel.Equals(Encoding.ASCII.GetString(data), StringComparison.OrdinalIgnoreCase))
                    {
                        JET_SETINFO setInfo = new JET_SETINFO();
                        setInfo.itagSequence = i;
                        Api.JetSetColumn(
                            _sesid,
                            _table,
                            _channelColumn,
                            null,
                            0,
                            SetColumnGrbit.None,
                            setInfo
                            );
                        break;
                    }
                }

                Api.JetUpdate(_sesid, _table);
            }
            catch (Exception)
            {
                Api.JetPrepareUpdate(_sesid, _table, JET_prep.Cancel);
                throw;
            }
        }
        /// <summary>
        /// Insert data into the data table. No record with the same key
        /// should exist.
        /// </summary>
        /// <param name="data">The data to add.</param>
        public void Insert(string subscriber, IEnumerable <string> channels)
        {
            Api.JetPrepareUpdate(_sesid, _table, JET_prep.Insert);
            try
            {
                // The easy part set the key
                Api.SetColumn(
                    _sesid,
                    _table,
                    _subscriberColumn,
                    subscriber,
                    Encoding.ASCII
                    );

                // Loop through all the channels and create them,
                // as this is a new record there is no need for checks
                foreach (var channel in channels)
                {
                    // Using tag sequence 0 wil mean the items are
                    // automatically pushed into the mv-column
                    JET_SETINFO setInfo = new JET_SETINFO();
                    setInfo.itagSequence = 0;

                    // Note the use of ASCII to take up half the space
                    // there is no reason either subscriber or channel
                    // will have more than this
                    byte[] data = Encoding.ASCII.GetBytes(channel);
                    Api.JetSetColumn(
                        _sesid,
                        _table,
                        _channelColumn,
                        data,
                        data.Length,
                        SetColumnGrbit.UniqueMultiValues,
                        setInfo
                        );
                }

                Api.JetUpdate(_sesid, _table);
            }
            catch (Exception)
            {
                Api.JetPrepareUpdate(_sesid, _table, JET_prep.Cancel);
                throw;
            }
        }
示例#16
0
        /// <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);
                }
        }
示例#17
0
        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);
        }
        public void Append(IEnumerable <string> channels)
        {
            Api.JetPrepareUpdate(_sesid, _table, JET_prep.Replace);
            try
            {
                // Get the existing channels
                var column = new JET_RETRIEVECOLUMN
                {
                    columnid = _channelColumn,
                    grbit    = RetrieveColumnGrbit.RetrieveTag
                };

                Api.JetRetrieveColumns(_sesid, _table, new[] { column }, 1);

                int count    = column.itagSequence;
                var existing = new string[count];
                for (int i = 1; i <= count; i++)
                {
                    JET_RETINFO retinfo = new JET_RETINFO {
                        itagSequence = i
                    };
                    byte[] data    = Api.RetrieveColumn(_sesid, _table, _channelColumn, RetrieveColumnGrbit.None, retinfo);
                    var    channel = Encoding.ASCII.GetString(data);
                    existing[i - 1] = channel;
                }

                // Loop through all the channels and create them,
                // as this is a new record there is no need for checks
                foreach (var channel in channels)
                {
                    // Only add the new ones
                    if (Array.IndexOf(existing, channel) > -1)
                    {
                        continue;
                    }

                    // Using tag sequence 0 wil mean the items are
                    // automatically pushed into the mv-column
                    count++;
                    JET_SETINFO setInfo = new JET_SETINFO();
                    setInfo.itagSequence = count;

                    // Note the use of ASCII to take up half the space
                    // there is no reason either subscriber or channel
                    // will have more than this
                    byte[] data = Encoding.ASCII.GetBytes(channel);
                    Api.JetSetColumn(
                        _sesid,
                        _table,
                        _channelColumn,
                        data,
                        data.Length,
                        SetColumnGrbit.UniqueMultiValues,
                        setInfo
                        );
                }

                Api.JetUpdate(_sesid, _table);
            }
            catch (Exception)
            {
                Api.JetPrepareUpdate(_sesid, _table, JET_prep.Cancel);
                throw;
            }
        }
        private void SetEntry(CacheEntry entry, JET_prep updateType)
        {
            Api.JetPrepareUpdate(_sesid, _table, updateType);
            try
            {
                // The easy part set the key
                Api.SetColumn(
                    _sesid,
                    _table,
                    _keyColumn,
                    entry.Key,
                    Encoding.Unicode
                    );

                Api.SetColumn(
                    _sesid,
                    _table,
                    _dataColumn,
                    entry.Data
                    );

                Api.SetColumn(
                    _sesid,
                    _table,
                    _callbacksColumn,
                    entry.PostEvicationCallbacks
                    );

                // Avoid race conditions on update by making sure the record
                // is clear
                if (updateType == JET_prep.Replace)
                {
                    // Get the existing channels
                    var column = new JET_RETRIEVECOLUMN
                    {
                        columnid = _dependencyColumn,
                        grbit    = RetrieveColumnGrbit.RetrieveTag
                    };
                    Api.JetRetrieveColumns(_sesid, _table, new[] { column }, 1);

                    // This is a bit tricky, note that when an item is removed all the
                    // itag sequences update to be one lower
                    int count = column.itagSequence;
                    for (int i = 0; i < count; i++)
                    {
                        JET_SETINFO setInfo = new JET_SETINFO {
                            itagSequence = 1
                        };
                        Api.JetSetColumn(
                            _sesid,
                            _table,
                            _dependencyColumn,
                            null,
                            0,
                            SetColumnGrbit.UniqueMultiValues,
                            setInfo
                            );
                    }

                    Api.SetColumn(_sesid, _table, _absoluteExpirationColumn, null);
                    Api.SetColumn(_sesid, _table, _lastAccessedColumn, null);
                    Api.SetColumn(_sesid, _table, _slidingExpirationColumn, null);
                }


                if (entry.AbsoluteExpiration > 0)
                {
                    Api.SetColumn(
                        _sesid,
                        _table,
                        _absoluteExpirationColumn,
                        entry.AbsoluteExpiration
                        );
                }
                else if (entry.SlidingExpiration > 0)
                {
                    Api.SetColumn(
                        _sesid,
                        _table,
                        _lastAccessedColumn,
                        Convert.ToInt64(entry.LastAccessed)
                        );

                    Api.SetColumn(
                        _sesid,
                        _table,
                        _slidingExpirationColumn,
                        entry.SlidingExpiration
                        );
                }

                // Loop through all the channels and create them,
                // as this is a new record there is no need for checks
                foreach (var dependency in entry.Dependencies)
                {
                    // Using tag sequence 0 wil mean the items are
                    // automatically pushed into the mv-column
                    JET_SETINFO setInfo = new JET_SETINFO();
                    setInfo.itagSequence = 0;

                    // Note the use of ASCII to take up half the space
                    // there is no reason either subscriber or channel
                    // will have more than this
                    byte[] data = Encoding.ASCII.GetBytes(dependency);
                    Api.JetSetColumn(
                        _sesid,
                        _table,
                        _dependencyColumn,
                        data,
                        data.Length,
                        SetColumnGrbit.UniqueMultiValues,
                        setInfo
                        );
                }

                Api.JetUpdate(_sesid, _table);
            }
            catch (Exception exp)
            {
                Api.JetPrepareUpdate(_sesid, _table, JET_prep.Cancel);
                throw exp;
            }
        }
示例#20
0
        // 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);
        }