entity framework and a generic repository.docx

Upload: zoranmatusko

Post on 01-Jun-2018

234 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/9/2019 Entity Framework and a Generic Repository.docx

    1/9

    Entity Framework and a Generic ReposIntroduction

    This article presents a high-level overview of multi-layered.Net application that implements the Repository Patternalong with the Entity Framework on its ata !ccess layer.

    The application uses "nversion of #ontrol to decouplea$stractions %interfaces& from implementations.'ore speci(cally) it uses Nin*ect to implementependency "n*ection.

    This separation of concerns allows us to dissect modulesand swap them with other implementations. This isachieved $y relying on contracts rather than

    implementations which results on code that is agnostic ofhow operations are implemented $ehind the interfaces.

    For e+ample) if you design your $usiness logic to rely onan interface that follows the Repository Pattern as adata persistence mechanism) for all intends and purposes)your $usiness logic will treat this dependency as amemory domain o$*ect collection. Therefore) forproduction you could provide an implementation of that

    dependency that uses the Entity Framework $ehind thescenes to store and retrieve data from a , data$ase. Forautomated unit testing) you could provide a completelydi/erent implementation that stores and retrieves datafrom in-memory o$*ects.

    Evidently) you could e+ecute all your tests against thedata$ase0 however) this setting greatly helps isolating unittests and cut dependencies on other resources) such as

    the data$ase) which may need more work to setup up andtear up for unit testing %especially true if you have otherteam mem$ers&.

    1efore moving forward) make sure you read 2hat3s"nversion of #ontrol4if you are not familiar with "nversionof #ontrol or ependency "n*ection or would like to hearmore a$out the advantages of interface-$ase design

    Note5 This article does not get into details on how to useall these technologies and patterns) instead it provides

    http://www.megustaulises.com/2013/03/entity-framework-and-generic-repository.htmlhttp://www.megustaulises.com/2012/12/what-is-inversion-of-control.htmlhttp://www.ninject.org/http://www.megustaulises.com/2012/12/what-is-inversion-of-control.htmlhttp://www.megustaulises.com/2012/12/what-is-inversion-of-control.htmlhttp://www.megustaulises.com/2012/12/what-is-inversion-of-control.htmlhttp://www.ninject.org/http://www.megustaulises.com/2012/12/what-is-inversion-of-control.htmlhttp://www.megustaulises.com/2012/12/what-is-inversion-of-control.htmlhttp://www.megustaulises.com/2013/03/entity-framework-and-generic-repository.html
  • 8/9/2019 Entity Framework and a Generic Repository.docx

    2/9

    references to other sources and shows you how they all (ttogether in a single application.

    The Repository Pattern

    The Repository Pattern6mediates $etween the domainand data mapping layers using a collection-like interfacefor accessing domain o$*ects6.

    "n a multi-layered application the Repository Pattern isimplemented in the ata !ccess layer%or Persistence ayer& and it interacts with the ,erviceayer and the ata ,ource $y mapping data to o$*ects

    $ack and forth. The following picture shows a we$application that uses a , data$ase in the $ack end.

    For each repository in the application we will create $oththe interface and the implementation. The interface willhave methods such as5 !dd) elete) Find) Get!ll) etc. 'ostmethods will return o$*ects or collections) others such as#ount will return integers. For e+ample) the Get!ll method

    for the 7ser3s Repository will return the list of all 7ser3so$*ects found in the data$ase.

    http://martinfowler.com/eaaCatalog/repository.htmlhttp://martinfowler.com/eaaCatalog/repository.html
  • 8/9/2019 Entity Framework and a Generic Repository.docx

    3/9

  • 8/9/2019 Entity Framework and a Generic Repository.docx

    4/9

    ?@8A88

    898:8;88?8@9A

    98999:9;99?9@

    :A:8:9:::;::?:@;A;8;9;:;;;;?;@

    D get0 set0

    publicGenericRepository%"$#onte+tFactory d$#onte+tFactory D

    #onte+t d$#onte+tFactory.Get$#onte+t%&0log og'anager.Getogger%GetType%&&0

    publicvirtual"uerya$leBtC Get!ll%& D return#onte+t.,etBtC%&0

    publicvirtual"uerya$leBtC Find!ll1y%,ystem.inH.E+pressio

    D return#onte+t.,etBtC%&.2here%predicate&0

    publicvirtualT FindFirst1y%,ystem.inH.E+pressions.E+pressio D return#onte+t.,etBtC%&.FirstIrefault%predicate&0

    publicvirtualvoid!dd%T entity& D #onte+t.,etBtC%&.!dd%entity&0

    publicvirtualvoidelete%T entity& D

    #onte+t.,etBtC%&.Remove%entity&0

    publicvirtualvoidelete%"uerya$leBtC entities& D foreach%T entity inentities.Toist%&& #onte+t.,etBtC%&.Remove%entity&0

    publicvirtualvoidEdit%T entity& D #onte+t.Entry%entity&.,tate ,ystem.ata.Entity,tate.'odi(e

  • 8/9/2019 Entity Framework and a Generic Repository.docx

    5/9

    ???@@A@8

    publicvirtualint,ave%&

    D try

    D return#onte+t.,ave#hanges%&0 catch%$EntityJalidationE+ception d$E+& D foreach%var validationErrors ind$E+.EntityJalidationErrors& D foreach%var validationError invalidationErrors.JalidationE D

    log.Error%string.Format%6Property5 DA Error5 D86) validati catch%E+ception e+& D log.Error%6,ave failed6) e+&0 returnA0

    publicvirtualT Find%intid&

    D return#onte+t.,etBtC%&.Find%id&0

    publicvoidRefresh%T entity& D #onte+t.Entry%entity&.Reload%&0

    publicvirtualint#ount%& D return#onte+t.,etBtC%&.#ount%&0

    publicvoidispose%& D if%#onte+t K null&

  • 8/9/2019 Entity Framework and a Generic Repository.docx

    6/9

    @9@:@;

    #onte+t.ispose%&0

    UsageThis is how you would declare your interface. Notice that$esides declaring the common code %!dd) elete) Get!ll)etc.& it also declares and additional method speci(c to thisrepository Get,u$ordinates%&4

    89:

    ;

    publicinterface"EmployeeRepository 5"GenericRepositoryBemploD"Enumera$leBemployeeC Get,u$ordinates%intid&0

    Lere is the implementation) notice the constructor isneeded here in order to o$tainan "$#onte+tFactory instance through ependency"n*ection. Evidently) the class must also implementGet,u$ordinates%&) this was *ust a simple e+ample on howyou can leverage the generic repository class and you arestill a$le to introduce class-speci(c code.4

    89:;?

    @8A88

    publicclassEmployeeRepository 5 GenericRepositoryBemployeD publicEmployeeRepository%"$#onte+tFactory d$#onte+tFactor 5 base%d$#onte+tFactory& D public"Enumera$leBemployeeC Get,u$ordinates%intid&

    D

    return%#onte+t asata'odel#ontainer&.Get,u$ordinates%id&0

    Sharing the DbContet ob!ect by using aDbContect"actory

    The "$#onte+tFactory interface is very straightforward) itonly declares a method and implements the "isposa$leinterface.

    4

  • 8/9/2019 Entity Framework and a Generic Repository.docx

    7/9

    89:;

    publicinterface"$#onte+tFactory 5 "isposa$leD $#onte+t Get$#onte+t%&0

    The implementation is also straightforward. The1#onte+tFactory creates an instance of $#onte+t in itsconstructor. For this reason) we can use the factory classto o$tain an instance of $#onte+t and as long as we usethe same factory we will $e sharing thesame $#onte+t instance across all repositories. This isactually very easy to do with a dependency in*ectioncontainer such as Nin*ect%$rieMy descri$ed in the ne+t

    section&.489:;?@8A88898:8;8

    8?8@9A98999:

    publicclass$#onte+tFactory 5 "$#onte+tFactoryD privatereadonly$#onte+t conte+t0public$#onte+tFactory%&

    Dconte+t ne#ata'odel#ontainer%&0

    public$#onte+t Get$#onte+t%&

    D returnconte+t0 publicvoidispose%&

    D if%conte+t K null&

    D conte+t.ispose%&0 G#.,uppressFinalie%this&0

    Using Nin!ect as The IoC ContainerNin*ectis very simple to setup. "n a few words you need to

    add a few dependencies to your pro*ect and a couple of

    http://www.ninject.org/http://www.ninject.org/http://www.ninject.org/http://www.ninject.org/
  • 8/9/2019 Entity Framework and a Generic Repository.docx

    8/9

    con(guration (les. The interesting piece is where you tellthe container the in*ection patternit will use %e.g.) in*ectdependencies through setters or constructors& and alsohow to map $etween interfaces and implementations. For

    e+ample) the Nin*ect2e$#ommon class provides thefollowing method to do this mapping54

    89:;?@8A88898:

    OOO BsummaryCOOO oad your modules or register your services hereKOOO BOsummaryCOOO Bparam name6kernel6CThe kernel.BOparamCprivatestaticvoidRegister,ervices%"ernel kernel&D OOrepoositories kernel.1indBid$conte+tfactoryC%&.ToBd$conte+tfactoryC%&."nReH kernel.1indBiemployeerepositoryC%&.ToBemployeerepositoryC%&0OO... more repositories...

    Ine thing to note is the use of the ReHuest scope for the$#onte+tFactory class which tells Nin*ect to create asingle instance of this o$*ect per LTTP reHuest. "n otherwords) every time a user reHuests a page) no mater howmany repository classes are involved) Nin*ect will create asingle factory class and) therefore) asingle $#onte+t instance. This also ensures that theo$*ect is destroyed once the reHuest completes. Goodstu/..

    Note5 "n the e+amples provided here "3ve $een usingdependency in*ection through constructors.

    Putting it all together $ Using theRepositoriesNow that you have created repositories you could eitheruse them directly on your controllers or on a service class.

    The following e+ample shows the Employee ,erviceo$taining the repositories from the ependency "n*ectioncontainer.

    4

    https://github.com/ninject/ninject/wiki/Injection-Patternshttps://github.com/ninject/Ninject.Web.Common/wiki/InRequestScopehttps://github.com/ninject/ninject/wiki/Injection-Patternshttps://github.com/ninject/Ninject.Web.Common/wiki/InRequestScope
  • 8/9/2019 Entity Framework and a Generic Repository.docx

    9/9

    89:;

    ?@8A88898:

    8;8