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: | ||
+ | |||
+ | |||
+ | |||
+ | <callout type=" | ||
+ | |||
+ | * [[../ | ||
+ | {{indexmenu> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | --- | ||
+ | |||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | <panel title=" | ||
+ | |||
+ | Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects. | ||
+ | |||
+ | ![MF](http:// | ||
+ | |||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ## Facts ## | ||
+ | * [0] Implemented by EF 4.2 DbSet (DbContext implements `UnitOfWork` Pattern) | ||
+ | |||
+ | |||
+ | ## Components ## | ||
+ | |||
+ | * [[IT/ | ||
+ | * 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, | ||
+ | |||
+ | |||
+ | ## 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' | ||
+ | * 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, | ||
+ | * 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' | ||
+ | |||
+ | The problem is the lazy loading and include statements. Each vendor has a different solution to the problem. | ||
+ | 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, | ||
+ | |||
+ | As far as I can tell, the only solution is to create a VendorSpecificRepositoryBase that returns IQueryable' | ||
+ | |||
+ | The reason they have to return IEnumerable, | ||
+ | |||
+ | If the domain is going to call the Reposotory directly -- and it's a quick down and dirty application, | ||
+ | |||
+ | |||
+ | ## Mocking ## | ||
+ | See: | ||
+ | * (post)[http:// | ||
+ | |||
+ | ## 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, | ||
+ | |||
+ | It certainly makes it easier in terms of method duplication, | ||
+ | |||
+ | |||
+ | |||
+ | ## Resources ## | ||
+ | |||
+ | Consider: | ||
+ | |||
+ | * Filtered DbSets: [http:// | ||
+ | * [Transactions](http:// | ||
+ | * [Key](http:// | ||
+ | * [NCommon](http:// | ||
+ | * [Good intro](http:// | ||
+ | * [...](http:// | ||
+ | * [http:// | ||
+ | * [http:// | ||
+ | * [http:// | ||
+ | * [http:// | ||
+ | * *really* Generic Repository [http:// | ||