/// <summary> /// Deletes a single table in the database /// </summary> /// <param name="tableName">Name of the table.</param> /// <exception cref="EsentObjectNotFoundException"> /// Thrown when the specified table can't be found. /// </exception> /// <exception cref="EsentTableInUseException"> /// Thrown when the specified table still has cursors open. /// </exception> /// <remarks> /// It is currently not possible to delete a table that is being used /// by a Cursor. All such Cursors must be disposed before the /// table can be successfully deleted. /// </remarks> public override void DropTable(string tableName) { lock (this.IsamSession) { this.CheckDisposed(); if (!this.Exists(tableName)) { throw new EsentObjectNotFoundException(); } TempTableHandle tempTableHandle = this.TempTableHandles[tableName]; if (tempTableHandle.CursorCount > 0) { throw new EsentTableInUseException(); } this.Tables.Remove(tableName); Api.JetCloseTable(this.IsamSession.Sesid, tempTableHandle.Handle); this.TempTableHandles.Remove(tempTableHandle.Name); this.IsamSession.IsamInstance.TempTableHandles.Remove(tempTableHandle.Guid.ToString()); } }
/// <summary> /// Releases the temporary table. /// </summary> /// <param name="tableName">Name of the table.</param> /// <param name="inInsertMode">if set to <c>true</c> [in insert mode].</param> internal void ReleaseTempTable(string tableName, bool inInsertMode) { lock (this.IsamSession) { TempTableHandle tempTableHandle = this.TempTableHandles[tableName]; tempTableHandle.InInsertMode = inInsertMode; tempTableHandle.CursorCount--; } }
/// <summary> /// Adds the specified temporary table handle. /// </summary> /// <param name="tempTableHandle">The temporary table handle.</param> public void Add(TempTableHandle tempTableHandle) { if (this.isKeyGuid) { this.Dictionary.Add(tempTableHandle.Guid.ToString().ToLower(CultureInfo.InvariantCulture), tempTableHandle); } else { this.Dictionary.Add(tempTableHandle.Name.ToLower(CultureInfo.InvariantCulture), tempTableHandle); } }
/// <summary> /// Opens a cursor over the specified table. /// </summary> /// <param name="tableName">the name of the table to be opened</param> /// <returns>a cursor over the specified table in this database</returns> public override Cursor OpenCursor(string tableName) { lock (this.IsamSession) { this.CheckDisposed(); if (!this.Exists(tableName)) { throw new EsentObjectNotFoundException(); } TableDefinition tableDefinition = this.Tables[tableName]; TempTableHandle tempTableHandle = this.TempTableHandles[tableName]; JET_TABLEID tableid; try { // if this is a Sort then we must always fail to dup the // cursor // // NOTE: this is a hack to work around problems in ESE/ESENT // that we cannot fix because we must work downlevel if (tableDefinition.Type == TableType.Sort) { throw new EsentIllegalOperationException(); } Api.JetDupCursor(this.IsamSession.Sesid, tempTableHandle.Handle, out tableid, DupCursorGrbit.None); tempTableHandle.InInsertMode = false; } catch (EsentIllegalOperationException) { if (tempTableHandle.CursorCount > 0) { throw new InvalidOperationException("It is not possible to have multiple open cursors on a temporary table that is currently in insert mode."); } else { tableid = tempTableHandle.Handle; } } Cursor newCursor = new Cursor(this.IsamSession, this, tableName, tableid, tempTableHandle.InInsertMode); tempTableHandle.CursorCount++; return(newCursor); } }
/// <summary> /// Adds the specified temporary table handle. /// </summary> /// <param name="tempTableHandle">The temporary table handle.</param> public void Add(TempTableHandle tempTableHandle) { if (this.isKeyGuid) { this.Dictionary.Add(tempTableHandle.Guid.ToString().ToLower(CultureInfo.InvariantCulture), tempTableHandle); } else { this.Dictionary.Add(tempTableHandle.Name.ToLower(CultureInfo.InvariantCulture), tempTableHandle); } }
/// <summary> /// Creates a single table with the specified definition in the database /// </summary> /// <param name="tableDefinition">The table definition.</param> /// <exception cref="EsentTableDuplicateException"> /// Thrown when the table definition overlaps with an already existing table. /// </exception> /// <exception cref="System.ArgumentException">A MaxKeyLength > 255 is not supported for indices over a temporary table on this version of the database engine.;tableDefinition</exception> public override void CreateTable(TableDefinition tableDefinition) { lock (this.IsamSession) { this.CheckDisposed(); // validate the table definition for creating a TT this.ValidateTableDefinition(tableDefinition); // convert the given table definition into an JET_OPENTEMPORARYTABLE // struct that we will use to create the TT JET_OPENTEMPORARYTABLE openTemporaryTable = this.MakeOpenTemporaryTable(tableDefinition); // check if the TT already exists if (this.Exists(tableDefinition.Name)) { throw new EsentTableDuplicateException(); } // do not allow the TT to be created if the session is in a // transaction. we disallow this to sidestep the problem where // JET will automatically close (and destroy) the TT if the // current level of the transaction is aborted if (this.IsamSession.TransactionLevel > 0) { // NOTE: i'm thinking that this requirement is pretty lame, // especially since it only hits us on an abort. I am going // to allow this for now and see what happens // throw new ArgumentException( "We do not currently allow you to create temp tables while inside of a transaction." ); } // create the TT JET_TABLEID tableid = new JET_TABLEID(); if (DatabaseCommon.CheckEngineVersion( this.IsamSession, DatabaseCommon.ESENTVersion(6, 0, 6000, 0), DatabaseCommon.ESEVersion(8, 0, 685, 0))) { VistaApi.JetOpenTemporaryTable(this.IsamSession.Sesid, openTemporaryTable); tableid = openTemporaryTable.tableid; } else { if (openTemporaryTable.cbKeyMost > 255) { throw new ArgumentException("A MaxKeyLength > 255 is not supported for indices over a temporary table on this version of the database engine.", "tableDefinition"); } Api.JetOpenTempTable2( this.IsamSession.Sesid, openTemporaryTable.prgcolumndef, openTemporaryTable.prgcolumndef.Length, openTemporaryTable.pidxunicode.lcid, openTemporaryTable.grbit, out tableid, openTemporaryTable.prgcolumnid); } // re-create the TT's schema to reflect the created TT TableDefinition tableDefinitionToCache = MakeTableDefinitionToCache(tableDefinition, openTemporaryTable); // cache the TT and its handle TempTableHandle tempTableHandle = new TempTableHandle( tableDefinitionToCache.Name, this.IsamSession.Sesid, tableid, tableDefinitionToCache.Type == TableType.Sort || tableDefinitionToCache.Type == TableType.PreSortTemporary); this.Tables.Add(tableDefinitionToCache); this.TempTableHandles.Add(tempTableHandle); this.IsamSession.IsamInstance.TempTableHandles.Add(tempTableHandle); } }