From: Michael D. <mik...@us...> - 2005-01-31 03:25:48
|
Update of /cvsroot/nhibernate/nhibernate/src/NHibernate/Impl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11156/NHibernate/Impl Modified Files: BatcherImpl.cs NonBatchingBatcher.cs SessionImpl.cs Log Message: implemented IDisposable on IBatcher. Index: SessionImpl.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Impl/SessionImpl.cs,v retrieving revision 1.62 retrieving revision 1.63 diff -C2 -d -r1.62 -r1.63 *** SessionImpl.cs 30 Jan 2005 19:36:16 -0000 1.62 --- SessionImpl.cs 31 Jan 2005 03:25:39 -0000 1.63 *************** *** 4105,4109 **** if( batcher!=null ) { ! // TODO: add batcher.Dispose() when IDisposable implemented by IBatcher } --- 4105,4109 ---- if( batcher!=null ) { ! batcher.Dispose(); } Index: BatcherImpl.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Impl/BatcherImpl.cs,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** BatcherImpl.cs 30 Jan 2005 19:39:12 -0000 1.16 --- BatcherImpl.cs 31 Jan 2005 03:25:39 -0000 1.17 *************** *** 20,28 **** private static int openReaderCount; ! /// <summary></summary> ! protected readonly ISessionImplementor session; ! /// <summary></summary> ! protected readonly ISessionFactoryImplementor factory; // batchCommand used to be called batchUpdate - that name to me implied that updates --- 20,26 ---- private static int openReaderCount; ! private readonly ISessionImplementor session; ! private readonly ISessionFactoryImplementor factory; // batchCommand used to be called batchUpdate - that name to me implied that updates *************** *** 35,46 **** private ISet readersToClose = new HashedSet(); ! // key = SqlString ! // value = IDbCommand private IDictionary commands; /// <summary> ! /// /// </summary> ! /// <param name="session"></param> public BatcherImpl( ISessionImplementor session ) { --- 33,46 ---- private ISet readersToClose = new HashedSet(); ! /// <summary> ! /// An IDictionary with a key of a SqlString and ! /// a value of an IDbCommand. ! /// </summary> private IDictionary commands; /// <summary> ! /// Initializes a new instance of the <see cref="BatcherImpl"/> class. /// </summary> ! /// <param name="session">The <see cref="ISessionImplementor"/> this Batcher is executing in.</param> public BatcherImpl( ISessionImplementor session ) { *************** *** 51,59 **** /// <summary> ! /// Gets the current Command that is contained for this Batch /// </summary> ! protected IDbCommand GetCommand() { ! return batchCommand; } --- 51,61 ---- /// <summary> ! /// Gets the current <see cref="IDbCommand"/> that is contained for this Batch /// </summary> ! /// <value>The current <see cref="IDbCommand"/>.</value> ! protected IDbCommand CurrentCommand { ! // in h2.0.3 this was a method GetCommand ! get { return batchCommand; } } *************** *** 161,166 **** public IDbCommand PrepareCommand( SqlString sql ) { ExecuteBatch(); ! LogOpenPreparedCommands(); // do not actually prepare the Command here - instead just generate it because --- 163,171 ---- public IDbCommand PrepareCommand( SqlString sql ) { + // a new IDbCommand is being prepared and a new (potential) batch + // started - so execute the current batch of commands. ExecuteBatch(); ! ! LogOpenPreparedCommand(); // do not actually prepare the Command here - instead just generate it because *************** *** 181,185 **** //TODO: figure out what to do with scrollable - don't think it applies // to ado.net since DataReader is forward only ! LogOpenPreparedCommands(); // do not actually prepare the Command here - instead just generate it because --- 186,190 ---- //TODO: figure out what to do with scrollable - don't think it applies // to ado.net since DataReader is forward only ! LogOpenPreparedCommand(); // do not actually prepare the Command here - instead just generate it because *************** *** 204,207 **** --- 209,213 ---- batchCommand = null; batchCommandSql = null; + CloseCommand( cmd, null ); // close the statement closeStatement(cmd) } *************** *** 247,251 **** readersToClose.Add( reader ); ! LogOpenReaders(); return reader; } --- 253,257 ---- readersToClose.Add( reader ); ! LogOpenReader(); return reader; } *************** *** 293,297 **** try { ! LogCloseReaders(); reader.Close(); } --- 299,303 ---- try { ! LogCloseReader(); reader.Close(); } *************** *** 312,316 **** { // no big deal ! log.Warn( "Could not close a JDBC statement", e ); } } --- 318,322 ---- { // no big deal ! log.Warn( "Could not close ADO.NET Command", e ); } } *************** *** 331,335 **** } ! LogClosePreparedCommands(); } --- 337,341 ---- } ! LogClosePreparedCommand(); } *************** *** 351,355 **** if( reader != null ) { ! LogCloseReaders(); reader.Close(); } --- 357,361 ---- if( reader != null ) { ! LogCloseReader(); reader.Close(); } *************** *** 364,367 **** --- 370,375 ---- public void ExecuteBatch() { + // if there is currently a command that a batch is + // being built for then execute it if( batchCommand != null ) { *************** *** 387,396 **** /// <summary> ! /// /// </summary> ! /// <param name="expectedRowCount"></param> public abstract void AddToBatch( int expectedRowCount ); ! /// <summary></summary> protected ISessionFactoryImplementor Factory { --- 395,415 ---- /// <summary> ! /// Adds the expected row count into the batch. /// </summary> ! /// <param name="expectedRowCount">The number of rows expected to be affected by the query.</param> ! /// <remarks> ! /// If Batching is not supported, then this is when the Command should be executed. If Batching ! /// is supported then it should hold of on executing the batch until explicitly told to. ! /// </remarks> public abstract void AddToBatch( int expectedRowCount ); ! /// <summary> ! /// Gets the <see cref="ISessionFactoryImplementor"/> the Batcher was ! /// created in. ! /// </summary> ! /// <value> ! /// The <see cref="ISessionFactoryImplementor"/> the Batcher was ! /// created in. ! /// </value> protected ISessionFactoryImplementor Factory { *************** *** 398,402 **** } ! /// <summary></summary> protected ISessionImplementor Session { --- 417,428 ---- } ! /// <summary> ! /// Gets the <see cref="ISessionImplementor"/> the Batcher is handling the ! /// sql actions for. ! /// </summary> ! /// <value> ! /// The <see cref="ISessionImplementor"/> the Batcher is handling the ! /// sql actions for. ! /// </value> protected ISessionImplementor Session { *************** *** 404,408 **** } ! private static void LogOpenPreparedCommands() { if( log.IsDebugEnabled ) --- 430,434 ---- } ! private static void LogOpenPreparedCommand() { if( log.IsDebugEnabled ) *************** *** 413,417 **** } ! private static void LogClosePreparedCommands() { if( log.IsDebugEnabled ) --- 439,443 ---- } ! private static void LogClosePreparedCommand() { if( log.IsDebugEnabled ) *************** *** 422,426 **** } ! private static void LogOpenReaders() { if( log.IsDebugEnabled ) --- 448,452 ---- } ! private static void LogOpenReader() { if( log.IsDebugEnabled ) *************** *** 430,434 **** } ! private static void LogCloseReaders() { if( log.IsDebugEnabled ) --- 456,460 ---- } ! private static void LogCloseReader() { if( log.IsDebugEnabled ) *************** *** 438,441 **** --- 464,553 ---- } + #region IDisposable Members + + /// <summary> + /// A flag to indicate if <c>Disose()</c> has been called. + /// </summary> + private bool _isAlreadyDisposed; + + /// <summary> + /// Finalizer that ensures the object is correctly disposed of. + /// </summary> + ~BatcherImpl() + { + Dispose( false ); + } + + /// <summary> + /// Takes care of freeing the managed and unmanaged resources that + /// this class is responsible for. + /// </summary> + public void Dispose() + { + log.Debug( "running BatcherImpl.Dispose()" ); + Dispose( true ); + } + + /// <summary> + /// Takes care of freeing the managed and unmanaged resources that + /// this class is responsible for. + /// </summary> + /// <param name="isDisposing">Indicates if this BatcherImpl is being Disposed of or Finalized.</param> + /// <remarks> + /// If this BatcherImpl is being Finalized (<c>isDisposing==false</c>) then make sure not + /// to call any methods that could potentially bring this BatcherImpl back to life. + /// </remarks> + protected virtual void Dispose(bool isDisposing) + { + if( _isAlreadyDisposed ) + { + // don't dispose of multiple times. + return; + } + + // free managed resources that are being managed by the AdoTransaction if we + // know this call came through Dispose() + if( isDisposing ) + { + foreach( IDataReader reader in readersToClose ) + { + try + { + LogCloseReader(); + reader.Dispose(); + } + catch( Exception e ) + { + log.Warn( "Could not dispose IDataReader", e ); + } + } + readersToClose.Clear(); + + foreach( IDbCommand cmd in commandsToClose ) + { + try + { + LogClosePreparedCommand(); + cmd.Dispose(); + } + catch( Exception e ) + { + // no big deal + log.Warn( "Could not dispose of ADO.NET Command", e ); + } + } + commandsToClose.Clear(); + } + + // free unmanaged resources here + + _isAlreadyDisposed = true; + // nothing for Finalizer to do - so tell the GC to ignore it + GC.SuppressFinalize( this ); + + } + + #endregion + } Index: NonBatchingBatcher.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Impl/NonBatchingBatcher.cs,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** NonBatchingBatcher.cs 31 Dec 2004 19:52:14 -0000 1.7 --- NonBatchingBatcher.cs 31 Jan 2005 03:25:39 -0000 1.8 *************** *** 5,16 **** { /// <summary> ! /// An implementation of the <c>IBatcher</c> inteface that does no batching /// </summary> internal class NonBatchingBatcher : BatcherImpl { /// <summary> ! /// /// </summary> ! /// <param name="session"></param> public NonBatchingBatcher( ISessionImplementor session ) : base( session ) { --- 5,17 ---- { /// <summary> ! /// An implementation of the <see cref="IBatcher" /> ! /// interface that does no batching. /// </summary> internal class NonBatchingBatcher : BatcherImpl { /// <summary> ! /// Initializes a new instance of the <see cref="NonBatchingBatcher"/> class. /// </summary> ! /// <param name="session">The <see cref="ISessionImplementor"/> the Batcher is in.</param> public NonBatchingBatcher( ISessionImplementor session ) : base( session ) { *************** *** 18,27 **** /// <summary> ! /// /// </summary> ! /// <param name="expectedRowCount"></param> public override void AddToBatch( int expectedRowCount ) { ! int rowCount = this.ExecuteNonQuery( this.GetCommand() ); //negative expected row count means we don't know how many rows to expect --- 19,36 ---- /// <summary> ! /// Executes the current <see cref="IDbCommand"/> and compares the row Count ! /// to the <c>expectedRowCount</c>. /// </summary> ! /// <param name="expectedRowCount"> ! /// The expected number of rows affected by the query. A value of less than <c>0</c> ! /// indicates that the number of rows to expect is unknown or should not be a factor. ! /// </param> ! /// <exception cref="HibernateException"> ! /// Thrown when there is an expected number of rows to be affected and the ! /// actual number of rows is different. ! /// </exception> public override void AddToBatch( int expectedRowCount ) { ! int rowCount = this.ExecuteNonQuery( this.CurrentCommand ); //negative expected row count means we don't know how many rows to expect *************** *** 33,37 **** /// <summary> ! /// /// </summary> /// <param name="ps"></param> --- 42,48 ---- /// <summary> ! /// This Batcher implementation does not support batching so this is a no-op call. The ! /// actual execution of the <see cref="IDbCommand"/> is run in the <c>AddToBatch</c> ! /// method. /// </summary> /// <param name="ps"></param> |