/// <summary> /// Sets the enumerator to its initial position, which is before the first element in the collection. /// </summary> public void Reset() { if (this.database != null) { lock (this.database.IsamSession) { if (this.cleanup) { if (!this.database.IsamSession.Disposed) { // BUGBUG: we will try to close an already closed tableid // if it was already closed due to a rollback. this could // cause us to crash in ESENT due to lack of full validation // in small config. we should use cursor LS to detect when // our cursor gets closed and thus avoid closing it again Api.JetCloseTable(this.database.IsamSession.Sesid, this.columnList.tableid); } } this.cleanup = false; this.moved = false; this.current = false; this.columnDefinition = null; } } else { this.enumerator.Reset(); } }
/// <summary> /// Adds the specified column definition. /// </summary> /// <param name="columnDefinition">The column definition.</param> public void Add(ColumnDefinition columnDefinition) { Dictionary.Add(columnDefinition.Name.ToLower(CultureInfo.InvariantCulture), columnDefinition); }
/// <summary> /// Advances the enumerator to the next element of the collection. /// </summary> /// <returns> /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. /// </returns> public bool MoveNext() { if (this.database != null) { lock (this.database.IsamSession) { JET_SESID sesid = this.database.IsamSession.Sesid; if (!this.moved) { Api.JetGetColumnInfo(sesid, this.database.Dbid, this.tableName, null, out this.columnList); this.cleanup = true; this.current = Api.TryMoveFirst(sesid, this.columnList.tableid); } else if (this.current) { this.current = Api.TryMoveNext(sesid, this.columnList.tableid); if (!this.current) { Api.JetCloseTable(sesid, this.columnList.tableid); this.cleanup = false; } } this.moved = true; this.columnDefinition = null; return this.current; } } else { return this.enumerator.MoveNext(); } }
/// <summary> /// Fetches the Column Definition for the specified columnid. /// </summary> /// <value> /// The <see cref="ColumnDefinition"/> for the specifed column identifier /// </value> /// <param name="columnid">The columnid.</param> /// <returns>The <see cref="ColumnDefinition"/> for the specified column identifier.</returns> public ColumnDefinition this[Columnid columnid] { get { if (this.database != null) { lock (this.database.IsamSession) { if (this.cachedColumnDefinition != columnid.Name.ToLower(CultureInfo.InvariantCulture) || this.columnUpdateID != DatabaseCommon.SchemaUpdateID) { JET_COLUMNBASE columnBase; Api.JetGetColumnInfo( this.database.IsamSession.Sesid, this.database.Dbid, this.tableName, columnid.Name, out columnBase); this.columnDefinition = ColumnDefinition.Load(this.database, this.tableName, columnBase); this.cachedColumnDefinition = columnid.Name.ToLower(CultureInfo.InvariantCulture); this.columnUpdateID = DatabaseCommon.SchemaUpdateID; } return this.columnDefinition; } } else { return (ColumnDefinition)this.Dictionary[columnid.Name.ToLower(CultureInfo.InvariantCulture)]; } } }
/// <summary> /// Creates a <see cref="ColumnDefinition"/> object representing the column passed in by <paramref name="columnBase"/>. /// </summary> /// <param name="database">The database.</param> /// <param name="tableName">Name of the table.</param> /// <param name="columnBase">The <see cref="JET_COLUMNBASE"/> object that represents this particular column.</param> /// <returns> /// A <see cref="ColumnDefinition"/> object based on the <paramref name="columnBase"/> object. /// </returns> internal static ColumnDefinition Load(IsamDatabase database, string tableName, JET_COLUMNBASE columnBase) { lock (database.IsamSession) { using (IsamTransaction trx = new IsamTransaction(database.IsamSession)) { JET_SESID sesid = database.IsamSession.Sesid; // load info for the column ColumnDefinition columnDefinition = new ColumnDefinition(); columnDefinition.columnid = new Columnid(columnBase); columnDefinition.name = columnDefinition.columnid.Name; columnDefinition.type = columnDefinition.columnid.Type; columnDefinition.flags = ColumnFlagsFromGrbits(columnBase.grbit); columnDefinition.maxLength = (int)columnBase.cbMax; columnDefinition.IsAscii = columnBase.cp == JET_CP.ASCII; // there is currently no efficient means to retrieve the // default value of a specific column from JET. so, we are // going to reach into the catalog and fetch it directly JET_TABLEID tableidCatalog; Api.JetOpenTable( sesid, database.Dbid, "MSysObjects", null, 0, OpenTableGrbit.ReadOnly, out tableidCatalog); Api.JetSetCurrentIndex(sesid, tableidCatalog, "RootObjects"); Api.MakeKey(sesid, tableidCatalog, true, MakeKeyGrbit.NewKey); Api.MakeKey( sesid, tableidCatalog, Converter.BytesFromObject(JET_coltyp.Text, true, columnBase.szBaseTableName), MakeKeyGrbit.None); Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ); JET_COLUMNBASE columnbaseCatalog; Api.JetGetTableColumnInfo(sesid, tableidCatalog, "ObjidTable", out columnbaseCatalog); uint objidTable = Api.RetrieveColumnAsUInt32(sesid, tableidCatalog, columnbaseCatalog.columnid).GetValueOrDefault(); Api.JetSetCurrentIndex(sesid, tableidCatalog, "Name"); Api.MakeKey(sesid, tableidCatalog, objidTable, MakeKeyGrbit.NewKey); Api.MakeKey(sesid, tableidCatalog, (short)2, MakeKeyGrbit.None); Api.MakeKey(sesid, tableidCatalog, columnBase.szBaseColumnName, Encoding.ASCII, MakeKeyGrbit.None); Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ); Api.JetGetTableColumnInfo(sesid, tableidCatalog, "DefaultValue", out columnbaseCatalog); byte[] defaultValueBytes = Api.RetrieveColumn(sesid, tableidCatalog, columnbaseCatalog.columnid); Columnid isamColumnid = columnDefinition.columnid; columnDefinition.defaultValue = Converter.ObjectFromBytes( isamColumnid.Coltyp, columnDefinition.IsAscii, defaultValueBytes); columnDefinition.ReadOnly = true; return columnDefinition; } } }
/// <summary> /// Creates a <see cref="ColumnDefinition"/> object representing the column passed in by <paramref name="columnList"/>. /// </summary> /// <param name="database">The database.</param> /// <param name="tableName">Name of the table.</param> /// <param name="columnList">The <see cref="JET_COLUMNLIST"/> object that represents the row in /// the temptable for this particular column.</param> /// <returns> /// A <see cref="ColumnDefinition"/> object based on the current row in the temptable /// represented by <paramref name="columnList"/>. /// </returns> internal static ColumnDefinition Load(IsamDatabase database, string tableName, JET_COLUMNLIST columnList) { lock (database.IsamSession) { using (IsamTransaction trx = new IsamTransaction(database.IsamSession)) { // load info for the column ColumnDefinition columnDefinition = new ColumnDefinition(); JET_SESID sesid = database.IsamSession.Sesid; // If we use the wide API (Vista+), then the temp table will be in UTF-16. // Technically, this should have worked in Vista. But there was a bug, and // it was fixed after Windows 7. Encoding encodingOfTextColumns = EsentVersion.SupportsWindows8Features ? Encoding.Unicode : Encoding.ASCII; string columnName = Api.RetrieveColumnAsString( database.IsamSession.Sesid, columnList.tableid, columnList.columnidcolumnname, encodingOfTextColumns); JET_COLUMNBASE columnbase; Api.JetGetColumnInfo(database.IsamSession.Sesid, database.Dbid, tableName, columnName, out columnbase); columnDefinition.columnid = new Columnid(columnbase); columnDefinition.name = columnDefinition.columnid.Name; columnDefinition.type = columnDefinition.columnid.Type; ColumndefGrbit grbitColumn = (ColumndefGrbit)Api.RetrieveColumnAsUInt32(sesid, columnList.tableid, columnList.columnidgrbit).GetValueOrDefault(); columnDefinition.flags = ColumnFlagsFromGrbits(grbitColumn); columnDefinition.maxLength = Api.RetrieveColumnAsInt32(sesid, columnList.tableid, columnList.columnidcbMax).GetValueOrDefault(); columnDefinition.IsAscii = columnbase.cp == JET_CP.ASCII; byte[] defaultValueBytes = Api.RetrieveColumn(sesid, columnList.tableid, columnList.columnidDefault); Columnid isamColumnid = columnDefinition.columnid; columnDefinition.defaultValue = Converter.ObjectFromBytes( isamColumnid.Coltyp, columnDefinition.IsAscii, defaultValueBytes); columnDefinition.ReadOnly = true; return columnDefinition; } } }
/// <summary> /// Sets the column. /// </summary> /// <param name="columnDefinition">The column definition.</param> /// <param name="index">The index.</param> /// <param name="obj">The object.</param> private void SetColumn(ColumnDefinition columnDefinition, int index, object obj) { lock (this.isamSession) { this.cursor.CheckDisposed(); using (IsamTransaction trx = new IsamTransaction(this.isamSession, true)) { Columnid columnid = columnDefinition.Columnid; this.SetColumn(columnid.InteropColumnid, columnid.Coltyp, columnid.IsAscii, index, obj); trx.Commit(); } } }
/// <summary> /// Retrieves the column. /// </summary> /// <param name="columnDefinition">The column definition.</param> /// <param name="index">The index.</param> /// <returns>The value stored within.</returns> private object RetrieveColumn(ColumnDefinition columnDefinition, int index) { lock (this.isamSession) { this.cursor.CheckDisposed(); using (IsamTransaction trx = new IsamTransaction(this.isamSession, true)) { Columnid columnid = columnDefinition.Columnid; return this.RetrieveColumn(columnid.InteropColumnid, columnid.Coltyp, columnid.IsAscii, index); } } }