c# - Should I Treat Entity Framework as an Unmanaged Resource? -


i working class uses reference ef in constructor.

i have implemented idisposable, i'm not sure if need destructor because i'm not can classify ef unmanaged resource.

if ef managed resource, don't need destructor, think proper example:

public exampleclass : idisposable {     public exampleclass(string connectionstringname, ilogger log)     {         //...         db = new entities(connectionstringname);     }      private bool _isdisposed;      public void dispose()     {         if (_isdisposed) return;          db.dispose();          _isdisposed= true;     } } 

if ef unmanaged, i'll go this:

public exampleclass : idisposable {     public exampleclass(string connectionstringname, ilogger log)     {         //...         db = new entities(connectionstringname);     }      public void dispose()     {         dispose(true);     }      ~exampleclass()     {         dispose(false);     }      private bool _isdisposed;      protected virtual void dispose(bool disposing)     {         if (_isdisposed) return;          // dispose of managed resources         if (disposing)         {             // dispose of managed resources; assumption here ef unmanaged.         }         // dispose of unmanaged resources         db.dispose();          _isdisposed = true;         //freed, no destructor necessary.         gc.suppressfinalize(this);      } } 

which 1 it?

you never want use finalizer (destructor) in case.

whether dbcontext contains unmanaged resources or not, , whether responsibly frees unmanaged resources or not, not relevant whether can try invoke dbcontext.dispose() finalizer.

the fact that, time have managed object (which instance of dbcontext is), never safe attempt invoke method on instance. reason that, time finalizer invoked, dbcontext object may have been gc-collected , no longer exist. if happen, nullreferenceexception when attempting call db.dispose(). or, if you're lucky, , db still "alive", exception can thrown within dbcontext.dispose() method if has dependencies on other objects have since been finalized , collected.

as "dispose pattern" msdn article says:

x not access finalizable objects in finalizer code path, because there significant risk have been finalized.

for example, finalizable object has reference finalizable object b cannot reliably use b in a’s finalizer, or vice versa. finalizers called in random order (short of weak ordering guarantee critical finalization).

also, note following eric lippert's when know wrong, part two:

myth: finalizers run in predictable order

suppose have tree of objects, finalizable, , on finalizer queue. there no requirement whatsoever tree finalized root leaves, leaves root, or other order.

myth: object being finalized can safely access object.

this myth follows directly previous. if have tree of objects , finalizing root, children still alive — because root alive, because on finalization queue, , children have living reference — children may have been finalized, , in no particularly state have methods or data accessed.


something else consider: trying dispose? concern making sure database connections closed in timely fashion? if so, you'll interested in ef documentation has this:

by default, context manages connections database. context opens , closes connections needed. example, context opens connection execute query, , closes connection when result sets have been processed.

what means that, default, connections don't need dbcontext.dispose() called closed in timely fashion. opened , closed (from connection pool) queries executed. so, though it's still idea make sure call dbcontext.dispose() explicitly, it's useful know that, if don't or forget reason, default, not causing kind of connection leak.


and finally, 1 last thing may want keep in mind, code posted doesn't have finalizer, because instantiate dbcontext inside constructor of class, possible dbcontext.dispose() method won't called. it's aware of special case not caught pants down.

for instance, suppose adjust code ever allow exception thrown after line in constructor instantiates dbcontext:

public exampleclass : idisposable {     public exampleclass(string connectionstringname, ilogger log)     {         //...         db = new entities(connectionstringname);          // let's pretend have code can throw exception here.         throw new exception("something went wrong after constructing db");     }      private bool _isdisposed;      public void dispose()     {         if (_isdisposed) return;          db.dispose();          _isdisposed= true;     } } 

and let's class used this:

using (var example = new exampleclass("connstring", log)) {     // ... } 

even though appears safe , clean design, because exception thrown inside constructor of exampleclass after new instance of dbcontext has been created, exampleclass.dispose() never invoked, , extension, dbcontext.dispose() never invoked either on newly created instance.

you can read more unfortunate situation here.

to ensure dbcontext's dispose() method invoked, no matter happens inside exampleclass constructor, have modify exampleclass class this:

public exampleclass : idisposable {     public exampleclass(string connectionstringname, ilogger log)     {         bool ok = false;         try          {             //...             db = new entities(connectionstringname);              // let's pretend have code can throw exception here.             throw new exception("something went wrong after constructing db");              ok = true;         }                 {             if (!ok)             {                 if (db != null)                 {                     db.dispose();                 }             }         }     }      private bool _isdisposed;      public void dispose()     {         if (_isdisposed) return;          db.dispose();          _isdisposed= true;     } } 

but above concern if constructor doing more creating instance of dbcontext.


Comments

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -