c# - Auto Dispose Sql Connections properly -


my application using 3 layers: dal / service / ul.

my typical dal class looks this:

public class ordersrepository : iordersrepository, idisposable {     private idbconnection _db;      public ordersrepository(idbconnection db) // constructor     {         _db = db;     }      public void dispose()     {         _db.dispose();     } } 

my service calls dal class (injecting database connection):

public class ordersservice : idisposable {     iordersrepository _orders;      public ordersservice() : this(new ordersrepository(new ajx.dal.dapperconnection().getconnection()))     {     }      public ordersservice(ordersrepository ordersrepo)     {         _orders = ordersrepo;     }      public void dispose()     {         _orders.dispose();     } } 

and within ui layer, how access service layer:

public class orderscontroller : controller, idisposable {     //     // get: /orders/     private ordersservice _orderservice;      public orderscontroller():this(new ordersservice())     {     }      public orderscontroller(ordersservice o)     {         _orderservice = o;     }      void idisposable.dispose()     {         _orderservice.dispose();     } } 

this works good. can see, relying on idisposable within every layer. ui disposes service object , service object disposes dal object , dal object disposes database connection object.

i sure there has better way of doing it. afraid users can forget dispose service object (within ui) , end many open database connections or worse. please advise best practice. need way auto-dispose database connections or other unmanaged resources (files etc).

your question comes principle of ownership:

he has ownership of resource, should dispose it.

although ownership can transferred, should not this. in case ownership of idbconnection transferred ordersservice ordersrepository (since ordersrepository disposes connection). in many cases ordersrepository can't know whether connection can disposed. can reused throughout object graph. in general, should not dispose objects passed on through constructor.

another thing consumer of dependency can't know if dependency needs disposal, since whether or not dependency needs disposed implementation detail. information might not available in interface.

so instead, refactor ordersrepository following:

public class ordersrepository : iordersrepository {     private idbconnection _db;      public ordersrepository(idbconnection db) {         _db = db;     } } 

since ordersrepository doesn't take ownership, idbconnection doesn't need dispose idbconnection , don't need implement idisposable. explicitly moves responsibility of disposing connection ordersservice. however, ordersservice doesn't need idbconnection dependency; depends on iordersrepository. why not move responsibility of building object graph out of ordersservice well:

public class ordersservice : idisposable {     private readonly iordersrepository _orders;      public ordersservice(iordersrepository ordersrepo) {         _orders = ordersrepo;     } } 

since ordersservice has nothing dispose itself, there's no need implement idisposable. , since has single constructor takes dependencies requires, class has become easier maintain.

so moves responsibility of creating object graph orderscontroller. should apply same pattern orderscontroller well:

public class orderscontroller : controller {     private ordersservice _orderservice;      public orderscontroller(ordersservice o) {         _orderservice = o;     } } 

again, class has become easier grasp , doesn't needs dispose anything, since doesn't has or took ownership of resource.

of course moved , postponed our problems, since still need create our orderscontroller. difference moved responsiblity of building object graphs single place in application. call place composition root.

dependency injection frameworks can making composition root maintainable, without di framework, build object graph quite easy in mvc implementing custom controllerfactory:

public class compositionroot : defaultcontrollerfactory {     protected override icontroller getcontrollerinstance(         requestcontext requestcontext, type controllertype) {         if (controllertype == typeof(orderscontroller)) {             var connection = new ajx.dal.dapperconnection().getconnection();              return new orderscontroller(                 new ordersservice(                     new ordersrepository(                         disposable(connection))));         }          else if (...) {             // other controller here.         }          else {             return base.getcontrollerinstance(requestcontext, controllertype);         }     }      public static void cleanuprequest() }         var items = (list<idisposable>)httpcontext.current.items["resources"];         if (items != null) items.foreach(item => item.dispose());     }      private static t disposable<t>(t instance)          t : idisposable {         var items = (list<idisposable>)httpcontext.current.items["resources"];         if (items == null) {             httpcontext.current.items["resources"] =                 items = new list<idisposable>();         }         items.add(instance);         return instance;     } } 

you can hook custom controller factory in global asax of mvc application this:

public class mvcapplication : system.web.httpapplication {     protected void application_start()     {         controllerbuilder.current.setcontrollerfactory(             new compositionroot());     }      protected void application_endrequest(object sender, eventargs e)     {         compositionroot.cleanuprequest();     } } 

of course, becomes easier when use dependency injection framework. instance, when use simple injector (i'm lead dev simple injector), can replace of following few lines of code:

using simpleinjector; using simpleinjector.integration.web; using simpleinjector.integration.web.mvc;  public class mvcapplication : system.web.httpapplication {     protected void application_start()     {         var container = new container();          container.registerperwebrequest<idbconnection>(() =>             new ajx.dal.dapperconnection().getconnection());          container.register<iordersrepository, ordersrepository>();         container.register<iordersservice, ordersservice>();          container.registermvccontrollers(assembly.getexecutingassembly());          container.verify();          dependencyresolver.setresolver(             new simpleinjectordependencyresolver(container));     } } 

there few interesting things going on in code above. first of all, calls register tell simple injector need return implementation should created when given abstraction requested. next, simple injector allows registering types web request lifestyle, makes sure given instance disposed when web request ends (just did in application_endrequest). calling registermvccontrollers, simple injector batch-register controllers you. supplying mvc simpleinjectordependencyresolver allow mvc route creation of controllers simple injector (just did controller factory).

although code might bit harder understand @ first, use of dependency injection container becomes valuable when application starts grow. di container keeping composition root maintainable.


Comments

Popular posts from this blog

c# - Unity IoC Lifetime per HttpRequest for UserStore -

I am trying to solve the error message 'incompatible ranks 0 and 1 in assignment' in a fortran 95 program. -

PHPMotion implementation - URL based videos (Hosted on separate location) -