This project has moved. For the latest updates, please go here.

Correct way to dispose of Esent objects

Aug 8, 2010 at 4:46 PM

What is the right way to close/dispose of Instances, Sessions,etc...?

When I have code (following the samples) of

            using (var instance = new Instance(...))
            {
	       ...

                using (var session = new Session(instance))
                {
                   ... 
                   using (var table = new Table(session, dbid, TableNameOpenTableGrbit.None))
                    {
		etc...... 

Everything is fine. However when the is code split to allow batching of writes for example and I try to dispose the tables/sessions/instance I see multiple errors in the output, e.g.

A first chance exception of type 'Microsoft.Isam.Esent.Interop.EsentErrorException' occurred in Esent.Interop.dll

A first chance exception of type 'Microsoft.Isam.Esent.Interop.EsentErrorException' occurred in Esent.Interop.dll

Exception closing Logging Database Session: Error SessionSharingViolation (JET_errSessionSharingViolation, Multiple threads are using the same session)

Exception closing Logging Database Session: Error SessionSharingViolation (JET_errSessionSharingViolation, Multiple threads are using the same session)

A first chance exception of type 'Microsoft.Isam.Esent.Interop.EsentErrorException' occurred in Esent.Interop.dll

LocalDatabaseTest.vshost.exe Warning: 0 : Non-finalized ESENT resource Microsoft.Isam.Esent.Interop.Transaction

LocalDatabaseTest.vshost.exe Warning: 0 : Exception finalizing Logging Database: Error TooManyActiveUsers (JET_errTooManyActiveUsers, Too many active database users)

Non-finalized ESENT resource Microsoft.Isam.Esent.Interop.Table

LocalDatabaseTest.vshost.exe Warning: 0 : Non-finalized ESENT resource Microsoft.Isam.Esent.Interop.Session

The data is saved correctly but the messages are disturbing (especially in a single threaded/user environment). I've tried using the various Close/End and Dispose methods on the objects with no success.

Aug 8, 2010 at 9:18 PM

Are you using tasks in some way? The session sharing violation should only appear if you migrate an open transaction between different OS threads.

 

Aug 9, 2010 at 4:52 AM

No everything is on single thead. 

I have however managed to stop the messages appearing by removing the Esent object Dispose method calls out of the destructors of my classes and into a seperate Close() method that is explicitly called when I'm done.

I still have a question about the actions to be taken to "shutdown" the database correctly.  The Table object has a Close() method, the Session object has a End() method, and the Instance object has a Term() method.  Which, if any, of these should be called?

Thanks for your quick response to my questions and of course for this excellent library.

Richard.

 

Aug 9, 2010 at 6:55 PM

It is the finalizers (destructors) that are the problem. They run on a separate thread so you do actually have a multi-threaded application. ESENT objects must be destroyed in a specific order (transaction, table, session then instance) so you can't dispose of the resources from a finalizer, because they will run in an arbitrary order.

Whenever possible you should have 'using' statement to make sure that ESENT resources, or objects that have ESENT resources are destroyed correctly. If something is missed then don't close the resource from the finalizer, you will have to wait for the instance to be closed to reclaim the resources. Note that the Instance class is derived from SafeHandle so it will always be closed.