it:ad:patterns:repository_pattern

no way to compare when less than two revisions

Differences

This shows you the differences between two versions of the page.


it:ad:patterns:repository_pattern [2023/11/04 03:29] (current) – created - external edit 127.0.0.1
Line 1: Line 1:
 +# IT:AD:Patterns:Repository Pattern #
 +
 +
 +
 +<callout type="Navigation" class="small">
 +
 +* [[../|(UP)]]
 +{{indexmenu>.#2|nsort tsort}}
 +
 +
 +
 +
 +---
 +
 +
 +</callout>
 +
 +
 +<panel title="Summary">
 +
 +Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
 +
 +![MF](http://martinfowler.com/eaaCatalog/repositorySketch.gif)
 +
 +
 +</panel>
 +
 +
 +## Facts ##
 +* [0] Implemented by EF 4.2 DbSet (DbContext implements `UnitOfWork` Pattern)
 +
 +
 +## Components ##
 +
 +* [[IT/AD/Patterns/UnitOfWork Pattern/]]
 +* Repository Pattern:  
 +    * According to [M.F.]() A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. 
 +
 +Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.
 +
 +
 +## Problem Definition ##
 +* A DataContext is for many Aggregate Root Entities
 +* A Repo is needed for each Aggregate Root Entity
 +* A Repo is always associated to one type of DataContext (during the lifespan of that repo it is for EF, or other, but it doesn't switch from EF DataContext to NHibernate Session or other such switch).
 +* But a Repo should be able to work against several DataContexts.
 +* SOLID would suggest that a Repo constructor should define up front what it needs...
 +    * It can define up front that it needs a IContext...
 +        *.. but this ties a Repo to only one DataContext (as ServiceLocator always returns the same Repo).
 +    * It can define up front instead that it needs an IContextManager, or IUoWManager if there is a 1-1 relationship, which will return a 'Current' UoW/Context.
 +* A Controller should declare up front which Repo it wants.
 +* Controller(IMyRepo)
 +    * MyRepo(IUoWManager)
 +* If an ObjectContext IS a UoW, then there is a one to one relationship.
 +    * And the scoping of multiple UoW's is via TransactionScope.
 +
 +
 +
 +
 +## Generic Repository ##
 +Let's get one thing out of the way first: one can make a *vendor-specific* generic Repository, but one can't make -- in a way that adds value -- a generic Repository that is portable across vendors.
 +
 +One can wrap up the IUnit of work, and Context:
 +
 +    //Create EF specific ObjectContext:
 +    using (ObjectContext origObjectContext = new XAct_App()){
 +      //Wrap in order to work with portable wrapper:
 +      using (IObjectContext objectContext = new EntityObjectContext(origObjectContext)){
 +        //Use it to define a new UoW:
 +        using (IUnitOfWork uow = new UnitOfWork(abstractObjectContext)){
 +          using (IRepository repository = new ExampleRepository(objectContext)){
 +            ...
 +            repository.MakeChanges(...);
 +            ...
 +            uow.Commit();
 +          }
 +        }
 +      }
 +    }
 +
 +but it really doesn't get you much further along. 
 +
 +The problem is the lazy loading and include statements. Each vendor has a different solution to the problem.  There is no .NET Framework portable Extension method for Including child objects, so to get access to these methods, one has to have a reference to the EF assemblies. It's as simple as that. 
 +If you try to wrap up all those juicy vendor extensions, you'll never finish -- and if you try to go for a lower common denominator, you'll be losing half of the advantages that ORM's can provide. Sounds like a bad strategy.
 +
 +As far as I can tell, the only solution is to create a VendorSpecificRepositoryBase that returns IQueryable's, enherit from that (eg: ContactsRepository) that uses vendor specific Extensions Methods (Include. etc) and exposes methods that return IEnumerable, not IQueryable().
 +
 +The reason they have to return IEnumerable, and not IQueryable, is to not infest the calling Domain layer with technology specific methods, including Repository (that's up to the Application Layer to orchestrate).
 +
 +If the domain is going to call the Reposotory directly -- and it's a quick down and dirty application, I guess it could expose its methods as IQueryable. Really wouldn't recommend it as a long term strategy.
 +
 +
 +## Mocking ##
 +See: 
 +* (post)[http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/] for ideas.
 +
 +## Ambiguity ##
 +
 +A Repository has a 1-1 relationship to its internal DbSet that is wraps in order to manage a single Aggregagate Entity .
 +If there is a cross relationship (for example, Vertices and Edges in a Graph, it's better to have two Repositories, linked by a common Context, instead of one Repository, with two DbSets.
 +
 +It certainly makes it easier in terms of method duplication, etc.
 +
 +
 +
 +## Resources ##
 +
 +Consider:
 +
 +* Filtered DbSets: [http://bit.ly/tUrV3H](http://bit.ly/tUrV3H)
 +* [Transactions](http://www.mssoftwareconsulting.com/msswc/blog/post/Unit-of-Work-Pattern-for-Entity-Framework-4-and-Unity.aspx)
 +* [Key](http://stackoverflow.com/a/4465417)
 +* [NCommon](http://www.java2s.com/Open-Source/CSharp/Library/ncommon/NCommon/Data/UnitOfWork.cs.htm)
 +    * [Good intro](http://stevemgentile.wordpress.com/category/ncommon/)
 +* [...](http://kitchaiyong.wordpress.com/2009/10/10/repository-specification-unit-of-work-persistence-ignorance-poco-with-microsoft-entityframework-4-0-part-2/)
 +* [http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application](http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application)
 +* [http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/advanced-entity-framework-scenarios-for-an-mvc-web-application](http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/advanced-entity-framework-scenarios-for-an-mvc-web-application)
 +* [http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application](http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application)
 +* [http://www.primaryobjects.com/CMS/Article122.aspx](http://www.primaryobjects.com/CMS/Article122.aspx)
 +* *really* Generic Repository [http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/](http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/)
  
  • /home/skysigal/public_html/data/pages/it/ad/patterns/repository_pattern.txt
  • Last modified: 2023/11/04 03:29
  • by 127.0.0.1