entity framework - Modern ORM vs Repository/IoW pattern -


i read lots of content usage of entity framework/nhibernate (or other modern orm) repository/unitofwork patterns. apparently community divided. repository pattern mandatory, others it's waste of time... well, come "own" design , wanted share in order feedback...

in past, company decided develop , use it's own orm. it's total disaster. performance, stability (and else) terrible. want switch orm , want keep ability switch orm another. indeed, using sharepoint 2010. means 3.5 , nhibernate 3.4 , entity framework 4. plan migrate sharepoint 2013 asap in order able rely on .net 4.5/ef 6.1/... have switch orm pretty soon.

to so, have developed set of classes implementing "idatabasecontext" interface.

public interface idatabasecontext : idisposable {     iqueryable<tentity> asqueryable<tentity>()         tentity : entitybase;     ilist<tentity> aslist<tentity>()         tentity : entitybase;      ilist<tentity> find<tentity>(expression<func<tentity, bool>> predicate)         tentity : entitybase;     long count<tentity>()         tentity : entitybase;      void add<tentity>(tentity entity)         tentity : entitybase;     void delete<tentity>(tentity entity)         tentity : entitybase;     void update<tentity>(tentity entity)         tentity : entitybase; } 

for example, prototype have decided use nhibernate:

public class nhibernatedbcontext : idatabasecontext {     private isession _session = null;      public nhibernatedbcontext(isessionfactory factory)     {         if (factory == null)             throw new argumentnullexception("factory");         _session = factory.opensession();     }      public iqueryable<tentity> asqueryable<tentity>()         tentity : entitybase     {         return _session.query<tentity>();     }      public ilist<tentity> aslist<tentity>()         tentity : entitybase     {         return _session.queryover<tentity>()                        .list<tentity>();     }      public ilist<tentity> find<tentity>(expression<func<tentity, bool>> predicate)         tentity : entitybase     {         ...     }      public long count<tentity>()          tentity : entitybase     {         return _session.queryover<tentity>()                        .rowcountint64();     }      public void add<tentity>(tentity entity)         tentity : entitybase     {         if (entity == null)             throw new argumentnullexception("entity");         usetransaction(() => _session.save(entity));     }      public void delete<tentity>(tentity entity)         tentity : entitybase     {         ...     }      public void update<tentity>(tentity entity)         tentity : entitybase     {         ...     }      private void usetransaction(action action)     {         using (var transaction = _session.begintransaction())         {             try             {                 action();                 transaction.commit();             }             catch             {                 transaction.rollback();                 throw;             }         }     }      public void dispose()     {         if (_session != null)             _session.dispose();     } } 

eventually, service layer (each entity associated service) relies on interface don't introduce dependency on orm technology.

public class countryservice<country> : iservice<country>     country : entitybase {     private idatabasecontext _context;      public genericservice(idatabasecontext context)     {         if (context == null)             throw new argumentnullexception("context");         _context = context;     }      public ilist<country> getall()     {         return _context.aslist<country>();     }      public ilist<country> find(expression<func<country, bool>> predicate)     {         return _context.find(predicate);     }      ... } 

eventually, call method service layer, need 2 lines of code:

    var service = new countryservice(new nhibernatedbcontext(...)));     or      var service = new countryservice(new testdbcontext(...)));     ... 

i find architecture quite simple , convenient use. didn't find (yet) drawback/flaws/errors.

so think? did miss big? there can improve?

thank feedback...

regards, sebastien

personally think approach solid. equally im surprised see approach different repository / unit of work pattern. iservice layer directly comparable basic unit of work layer combined repository layer implemented via interface. repository layer should implement interface , injected or discovered core layer avoid dependency on underlying orm.

the actual implementation of repository , unit of work layers specific underlying orm. replace repositoryef class respositorynh or vice versa. if done , used dependency injection, core application never knows orm is.

the problem peoples repository patterns, leak underlying orm allowing code accesses orm directly or leaks orms structures.

eg if irepository exposed dbset or context entity framework, whole app can locked ef.

eg unit of work interface

 public interface iluw  {     irepositorybase<tpoco> getrepository<tpoco>() tpoco : baseobject, new();     void commit(operationresult operationresult=null, bool silent=false); } 

and irepositorybase interface

 public interface irepositorybase<tpoco> : irepositorycheck<tpoco>  tpoco : baseobject,new() {     void shortdump();     object originalpropertyvalue(tpoco poco, string propertyname);        ilist<objectpair> getchanges(object poco, string singlepropname=null);     iqueryable<tpoco> allq();     bool any(expression<func<tpoco, bool>> predicate);     int count();     iqueryable<tpoco> getlistq(expression<func<tpoco, bool>> predicate);     ilist<tpoco> getlist(expression<func<tpoco, bool>> predicate);     ilist<tpoco> getlistofids(list<string>ids );     iorderedqueryable<tpoco> getsortedlist<tsortkey>(expression<func<tpoco, bool>> predicate,                                                      expression<func<tpoco, tsortkey>> sortby, bool descending);       iqueryable<tpoco> getsortedpagelist<tsortkey>(expression<func<tpoco, bool>> predicate,                                                   expression<func<tpoco, tsortkey>> sortbypropertyname,                                                    bool descending,                                                   int skiprecords,                                                    int takerecords);      tpoco find(params object[] keyvalues);     tpoco find(string id); // single key in string format, must eb converted underlying type first.      int deletewhere(expression<func<tpoco, bool>> predicate);     bool delete(params object[] keyvalues);     tpoco get(expression<func<tpoco, bool>> predicate);     tpoco getlocalthendb(expression<func<tpoco, bool>> predicate);     ilist<tpoco> getlistlocalthendb(expression<func<tpoco, bool>> predicate);     tu getprojection<tu>(expression<func<tpoco, bool>> predicate, expression<func<tpoco, tu>> columns);     /// <summary>     /// use projection  enter anonymous type  s => new { s.id , s.username});     /// </summary>     ilist<tu> getprojectionlist<tu>(expression<func<tpoco, bool>> predicate, expression<func<tpoco, tu>> columns);       bool add(object poco,bool withcheck=true);     bool remove(object poco);     bool change(object poco, bool withcheck=true);     bool addorupdate(tpoco poco, bool withcheck = true);   } 

Comments

Popular posts from this blog

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -

ubuntu - Selenium Node Not Connecting to Hub, Not Opening Port -