Index: System.Data.SQLite/SQLiteSession.cs ================================================================== --- System.Data.SQLite/SQLiteSession.cs +++ System.Data.SQLite/SQLiteSession.cs @@ -284,13 +284,27 @@ #endregion /////////////////////////////////////////////////////////////////////////// #region SQLiteSessionHelpers Class + /// + /// This class contains some static helper methods for use within this + /// subsystem. + /// internal static class SQLiteSessionHelpers { #region Public Methods + /// + /// This method checks the byte array specified by the caller to make + /// sure it will be usable. + /// + /// + /// A byte array provided by the caller into one of the public methods + /// for the classes that belong to this subsystem. This value cannot + /// be null or represent an empty array; otherwise, an appropriate + /// exception will be thrown. + /// public static void CheckRawData( byte[] rawData ) { if (rawData == null) @@ -307,64 +321,134 @@ #endregion /////////////////////////////////////////////////////////////////////////// #region SQLiteConnectionLock Class + /// + /// This class is used to hold the native connection handle associated with + /// a open until this subsystem is totally + /// done with it. This class is for internal use by this subsystem only. + /// internal abstract class SQLiteConnectionLock : IDisposable { #region Private Constants + /// + /// The SQL statement used when creating the native statement handle. + /// There are no special requirements for this other than counting as + /// an "open statement handle". + /// private const string LockNopSql = "SELECT 1;"; /////////////////////////////////////////////////////////////////////// + /// + /// The format of the error message used when reporting, during object + /// disposal, that the statement handle is still open (i.e. because + /// this situation is considered a fairly serious programming error). + /// private const string StatementMessageFormat = "Connection lock object was {0} with statement {1}"; #endregion /////////////////////////////////////////////////////////////////////// #region Private Data + /// + /// The wrapped native connection handle associated with this lock. + /// private SQLiteConnectionHandle handle; + + /// + /// The flags associated with the connection represented by the + /// value. + /// private SQLiteConnectionFlags flags; /////////////////////////////////////////////////////////////////////// + /// + /// The native statement handle for this lock. The garbage collector + /// cannot cause this statement to be finalized; therefore, it will + /// serve to hold the associated native connection open until it is + /// freed manually using the method. + /// private IntPtr statement; #endregion /////////////////////////////////////////////////////////////////////// #region Public Constructors + /// + /// Constructs a new instance of this class using the specified native + /// connection handle and associated flags. + /// + /// + /// The wrapped native connection handle to be associated with this + /// lock. + /// + /// + /// The flags associated with the connection represented by the + /// value. + /// + /// + /// Non-zero if the method should be called prior + /// to returning from this constructor. + /// public SQLiteConnectionLock( SQLiteConnectionHandle handle, - SQLiteConnectionFlags flags + SQLiteConnectionFlags flags, + bool autoLock ) { this.handle = handle; this.flags = flags; - Lock(); + if (autoLock) + Lock(); } #endregion /////////////////////////////////////////////////////////////////////// #region Protected Methods + /// + /// Queries and returns the wrapped native connection handle for this + /// instance. + /// + /// + /// The wrapped native connection handle for this instance -OR- null + /// if it is unavailable. + /// protected SQLiteConnectionHandle GetHandle() { return handle; } /////////////////////////////////////////////////////////////////////// + /// + /// Queries and returns the flags associated with the connection for + /// this instance. + /// + /// + /// The value. There is no return + /// value reserved to indicate an error. + /// protected SQLiteConnectionFlags GetFlags() { return flags; } /////////////////////////////////////////////////////////////////////// + /// + /// Queries and returns the native connection handle for this instance. + /// + /// + /// The native connection handle for this instance. If this value is + /// unavailable or invalid an exception will be thrown. + /// protected IntPtr GetIntPtr() { if (handle == null) { throw new InvalidOperationException( @@ -384,10 +468,18 @@ #endregion /////////////////////////////////////////////////////////////////////// #region Public Methods + /// + /// This method attempts to "lock" the associated native connection + /// handle by preparing a SQL statement that will not be finalized + /// until the method is called (i.e. and which + /// cannot be done by the garbage collector). If the statement is + /// already prepared, nothing is done. If the statement cannot be + /// prepared for any reason, an exception will be thrown. + /// public void Lock() { CheckDisposed(); if (statement != IntPtr.Zero) @@ -421,10 +513,16 @@ } } /////////////////////////////////////////////////////////////////////// + /// + /// This method attempts to "unlock" the associated native connection + /// handle by finalizing the previously prepared statement. If the + /// statement is already finalized, nothing is done. If the statement + /// cannot be finalized for any reason, an exception will be thrown. + /// public void Unlock() { CheckDisposed(); if (statement == IntPtr.Zero) @@ -441,10 +539,13 @@ #endregion /////////////////////////////////////////////////////////////////////// #region IDisposable Members + /// + /// Disposes of this object instance. + /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } @@ -451,11 +552,18 @@ #endregion /////////////////////////////////////////////////////////////////////// #region IDisposable "Pattern" Members + /// + /// Non-zero if this object instance has been disposed. + /// private bool disposed; + + /// + /// Throws an exception if this object instance has been disposed. + /// private void CheckDisposed() /* throw */ { #if THROW_ON_DISPOSED if (disposed) { @@ -465,10 +573,17 @@ #endif } /////////////////////////////////////////////////////////////////////// + /// + /// Disposes or finalizes this object instance. + /// + /// + /// Non-zero if this object is being disposed; otherwise, this object + /// is being finalized. + /// protected virtual void Dispose(bool disposing) { try { if (!disposed) @@ -527,10 +642,13 @@ #endregion /////////////////////////////////////////////////////////////////////// #region Destructor + /// + /// Finalizes this object instance. + /// ~SQLiteConnectionLock() { Dispose(false); } #endregion @@ -1665,11 +1783,11 @@ public SQLiteSession( SQLiteConnectionHandle handle, SQLiteConnectionFlags flags, string databaseName ) - : base(handle, flags) + : base(handle, flags, true) { this.databaseName = databaseName; InitializeHandle(); } @@ -2129,11 +2247,11 @@ #region Private Constructors internal SQLiteChangeSetBase( SQLiteConnectionHandle handle, SQLiteConnectionFlags flags ) - : base(handle, flags) + : base(handle, flags, true) { // do nothing. } #endregion