If you take a look at this SO question I have a question on the next step.
Imagine you have two repositories generating Items and SubItems. I also have a UnitOfWork which acts as a context for changes to the (in this simple case) two different items.
There seem to be a few ways of generating a UnitOfWork, sometimes this is injected into the repository, sometimes this can be generated by a factory (and then either injected or retrieved from the factory.
My question is how does the UnitOfWork notify the repositories that its changes are now to be committed?
I guess I can have the repository subscribe to events on the UnitOfWork for commit/rollback.
Second question, the idea of the unit of work is, if I have this right, to co-ordinate updates that may conflict. Using my example of Item and SubItem (an Item has a number of SubItems) the UnitOfWork coordinates this so the Item is written first allowing the SubItem to be written? Now I seem to need the unit of work to know about the repositories which seems wrong.
Thanks.
The way I structured my repository was to have the UnitOfWork simply be a "token", spawned by a BeginUnitOfWork() method on the Repo, that then had to be passed to pretty much any other method on the Repo that made DB calls. The only thing it has to know how to do, conceptually, is be disposed, which when that happens causes the NHibernate session associated with that UOW to be closed. It does this by being given a delegate to a protected method in the Repo that it then called back in its Dispose method. What this does for me is completely abstract the actual data-access mechanism; I can implement the same pattern regardless of the back end, and users of the pattern cannot hack the UnitOfWork to get at the actual data-access mechanism.
YMMV; it does require classes that need to perform DB objects to be dependent on the repository as well as the unit of work. You could use additional delegates to expose methods on the UnitOfWork itself that would allow it to be the only dependency.
Related
Is it correct to create Unit of Work in order to share the DbContext among the Repositories?
If isn't what is the recommendation? I really think it is needed to share the DbContext sometimes.
I'm asking this because of the answer for this question: In-memory database doesn't save data
Is it correct to create Unit of Work in order to share the DbContext among the Repositories?
It is design decision, but yes. There is no problem in doing that. It is absolutely valid that code from multiple repositories is executed under one single connection.
I really think it is needed to share the DbContext sometimes.
Absolutely; there are many times when you need to share DbContext.
Your linked answer is really good. I specially like the three points it mention. OP on that question is doing some unnecessary complicated things like Singleton, Service Locator and Async calls without understanding how they work. All these are good things but only if they are used at right time at right place.
Following is from your linked answer:
The best thing is that all of these could be avoided if people stopped attempting to create a Unit of Work + Repository pattern over yet another Unit of Work and Repository. Entity Framework Core already implements these:
Yes; this is true. But even so, repository and UoW may be helpful in some cases. This is design decision based on business needs. I have explained this in my answers below:
https://stackoverflow.com/a/49850950/5779732
https://stackoverflow.com/a/50877329/5779732
Using ORM directly in calling code has following issues:
It makes code little more complicated.
Database code is merged in business logic.
As many ORM objects are used in-line in calling code, it is very hard to unit test the code.
All those issues could be overcome by creating Concrete Repositories in Data Access Layer. DAL should expose concrete repositories to calling code (BLL or Services or Controller whatever) through interfaces. This way, your database and ORM code is fully consumed in DAL and you can easily unit-test calling code by mocking repositories. Refer this article explaining benefit of repository even with ORMs.
Apart from all above, one other issue generally discussed is "What if we decide to change ORM in future". This is entirely false in my personal understanding. It happens very rarely and in most cases, should not be considered while design.
I recommend avoid overthinking and over-design. Focus on your business objectives.
Refer this example code to understand how to inject UoW in repositories. The code sample is with Dapper. But overall design may still useful to you.
What you need is a class that contains multiple repositories and creates a UoW. Then, when you have a use case in which you need to use multiple repositories with shared UoW, this class creates it and pass it to repositories.
I typically call this class Service, but I think there is not some standardized naming.
Does having multiple repositories increase resource usage?
I have followed this tutorial for adding a repository service that holds a database context: https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api
In the tutorial the repository is for managing a Todo item. In my own app I have several different types of items and activities that I need a context for. Should I create an individual repository for each? For instance one repository for enquiries, another for user usage metrics? Is there any overhead or penalty for doing this?
Should I create an individual repository for each? For instance one repository for enquiries, another for user usage metrics? Is there any overhead or penalty for doing this?
Yes. No.
Generally you want to have one repository per entity type because each entity type is going to more than likely require operations specific to its type beyond the cliche CRUD operations. The aim of the repo is to eliminate duplicate data query logic that would otherwise be littered about your application.
e.g.
interface IRepo { CRUD }
protected abstract class RepoBase<T> : IRepo
{
// CRUD implementation
}
public class PatientRepo : RepoBase<Patient>
{
List<IPatient> GetAllTerminallyIllPatients();
}
public class MusicRepo : RepoBase<Music>
{
List<ISong> GetAllSongsByArtist (string artist);
}
Note how each repo in my feeble example is customised to the entity type. If you didn't do this your single repo would quickly
become hard to find that method you're after
unmanageble with the potential for 100s of methods
lead to increased probability of source control conflict due to all code being in one file
You might want to consider splitting your repos into repos and unit of work classes because:
Repositories should not have semantics of your database. It should
be like a collection of objects in memory and should not methods like
update and save. - Mosh
You can learn more from the tutorial in the link below.
Does having multiple repositories increase resource usage?
Generally no, because for any given operation, all of your interested repos would be attached to the same database context instance. It is the context that is expensive, not the repo.
Tell me more
Repository Pattern with C# and Entity Framework, Done Right
As shown in the link provided The Repository pattern can be used to abstract the data access into an interface, in the example: ITodoRepository.
Why do you abstract data access? This way you could easily switch data-access layer by implementing a different class of ITodoRepository Say if you want to test your logic with unit tests, or if the possibility exists you wont be using entity framework anymore in the future.
If this is not the case and you are building a small project with no such future additions (unit tests/switch data-access layer) Making use of the Repository pattern is only extra work without any benefits.
So you should decide if the extra work of making the repository pattern outweighs the benefits for your project.
For each concrete class I have a Manager class. This class has methods like GetAll(), GetById(), Save, etc.
I've made these manager classes a Singleton because I always need one instance, and I have the ability to cache results. For example, when I call GetAll() and the next time I need this method again, the manager don't have to go to the database, it can return the cached results.
Is this a good approach? Or is there a better alternative way?
What you call manager classes are really "repositories"
Repositories should only work at an aggregate root level, not one repository per class. E.g. if I have an Order class which has a collection of OrderItem, then an Order repository would exist that would have Get/GetAll methods - as the Order is the agg root in this case.
All repository classes would usually be singleton classes, where you can usually enforce this easily via an IOC container.
Overall, I would say your approach of one "repository" per entity is bad - stick to one repository per aggregate root instead.
Why not include them as part of the concrete class but static? Saves the need for two seperate classes.
It sounds like you are close to implementing the Repository pattern, but not quite all the way there. I'd suggest looking into it. I wouldn't make them Singletons -- it makes it too hard to mock them out for your unit tests so you end up adding back doors to defeat the Singleton for testing. A cache makes a nice Singleton object, but why not simply share the cache this way instead of multiplying Singletons?
For testing/mocking purposes, I would advise against using a Manager/Repository Singleton.
If you do want to cache results, then I would suggest delegating to a dedicated Cache class. Any static magic can be contained within the Cache class and your Manager/Repository's semantics can be kept clean.
From a Single Responsibility Principle point of view, I should be able to understand how a Manager/Repository works without having to understand your caching scheme.
I've just started a new project and have naturally opted to use a lot of new tech.
I'm using (Fluent) NHibernate, ASP.NET MVC 3 and am trying to apply the Repository pattern.
I've decided to seperate my Business Logic into a seperate project and define services which wrap my repositories so that I can return POCOs instead of the NHibernate proxies and maintain more seperation between my Front end and DA logic. This will also give me the power to easily provide the same logic as an API later (a requirement).
I have chosen to use a generic IRepository<T> interface where T is one of my NHibernate mapped Entities which all implement IEntity (my interface only a marker really).
The problem is this goes against the aggregate root pattern and I'm starting to feel the pain of the anemic domain model.
If I change an object that is hanging of another
Root <- changed
Child <- changed
In my service I have to do the following:
public void AddNewChild(ChildDto child, rootId)
{
var childEntity = Mapper.Map<ChildDto,ChildEntity>(child);
var rootEntity = _rootrepository.FindById(rootId);
rootEntity.Children.Add(childEntity);
_childRepository.SaveOrUpdate(child);
_rootRepository.SaveOrUpdate(root);
}
If I don't save the child first I get an exception from NHibernate. I feel like my generic repository (I currently require 5 of them in one service) is not the right way to go.
public Service(IRepository<ThingEntity> thingRepo, IRepository<RootEntity> rootRepo, IRepository<ChildEntity> childRepo, IRepository<CategoryEntity> catRepo, IRepository<ProductEntity> productRepo)
I feel like instead of making my code more flexible, it's making it more brittle. If I add a new table I need to go and change the constructor in all my tests (I'm using DI for the implementation so that's not too bad) but it seems a bit smelly.
Does anyone have any advice on how to restructure this sort of architecture?
Should I be making my repositories more specific? Is the service abstraction layer a step too far?
EDIT: There's some great related questions which are helping:
Repository Pattern Best Practice
repository pattern help
Architectural conundrum
When you have an Aggregate, the Repository is the same for the aggregate parent (root) and its children because the life cycle of the children is controlled by the root object.
Your "Save" method for the root object type should be also directly responsible for persisting the changes to the children records instead of delegating it into yet another repository(ies).
Additionally, in a "proper" Aggregate pattern, the child records have no identity of their own (at least one that is visible outside the Aggregate). This has several direct consequences:
There can be no foreign keys from outside records/aggregates to those children records.
Resulting from point 1., every time you save the root object state, you can delete and recreate the child records on the database. This usually will make your persistence logic easier if you bump into precedence problems.
Note: the reverse case of 1. is not true. Child records in an aggregate can have foreign keys to other root records.
I feel like instead of making my code more flexible, it's making it more brittle. If I add a new table I need to go and change the constructor in all my tests (I'm using DI for the implementation so that's not too bad) but it seems a bit smelly.
Implement the Unit Of Work pattern in your repository. That means practically you have a unit of work class which holds your services inject via ctor or property injection. Futheremore it holds a commit and/or transaction method. Only inject the IUnitOfWork instance in your services. When you add a repository you just have to change the unit of work not touch the business logic (services).
Here's where I'm up to.
I have a generic Repository class Repository<TKey, TValue>. It has the usual Repository pattern methods.
Each Repository takes an IContext<TKey, TValue> in its constructor which provides the persistence for the repository.
I have specialised repositories which are composed of a generic Repository and then methods tailored to repository actions that are specific to the specialised object. So if I had a specialised repository for Kitten objects, It would have methods to ClimbTree (probably taking a tree object) but not a BuryBone(Bone bone) method. The point I'm making badly is It creates an association between the kitten and its tree which needs to be persisted. void CleanWhiskers() might be a simpler example. This sets the Kittens whiskers to clean.
So I'm now thinking of a scheme for related child objects persistence and starting to wonder if I'm already going a bit wrong.
I started with slightly ugly methods on the repository to create child objects. So Kitten repository would have a method CreateFurBall() which would add a FurBall object to the Kitten's FurBall collection AND add a Furball to the FurBall Repository to be persisted (Actually the same object).
I've now changed to a system where I have something akin to an ObservableCollection which notifies its parent repository when a POCO is added. So I can just create a POCO furball and added it to the collection which would then be automatically registered with the furball repository.
First off I'll have nHibernate implemented in the contexts, I think this maps fairly well. This is a really open question, for anyone that's been down this route before, can you see anything that makes you go "STOP!!"
I should have thought that methods such as ClimbTree(), BuryBone(), CreateFurBall() and CleanWhiskers() belong on the domain objects, not on the repositories.
The repository should handle persistence of the aggregate roots - i.e. let you query for Kittens, Save and Update them.
Anything you want to do with the kittens between instantiation and persistence is the prerogative of the Domain.
Nelson is correct.
I think there may be a confusion between the two ways of creating furballs. If a kitten is stored in the database with three furballs, then when it is pulled from the database, the kitten should be injected with his furball-data and the furball collection should be initialized from the furball-data.
When the application wants to add a furball to the kitten, then a furball should be by the kitten via Kitten.CreateFurBall(). I am making the assumption here that a furball is owned by the kitten and the furballs are not common to other kittens. If the furball is sufficently complex, you may need to abstract the creation of the furball to a FurballFactory that the kitten holds a lazy reference to.
As far as the creation of the Kitten entity, it can probably be best handled by having a reference to a KittenFactory in your KittenRepository which accepts the dto for the kitten and builds a kitten from it.
The biggest problem that you have demonstrated is in the Kitten.BuryBone(Bone bone) method. Kittens don't bury bones. Dogs do.
I might be slightly off-topic but I just wanted to put my two cents in about the repository pattern.
The repository pattern is great, especially when you put them all behind interfaces so that they can be swapped out easily. I create a repository for every entity. BrokenGlass is right in that the methods are usually very generic and don't contain much beyond persistence logic. I am usually a little less strict with the type of logic that makes it into a repository. For instance, some people think it is sinful to put paging logic in a repository, but I disagree.
I use Entity Framework and LINQ to SQL quite a bit. In order to page results from these I need the LINQ to operate on IQueryable<entity> so that the paging happens at the database level. I do not like to expose IQueryable outside of my repository. Because what if someday my repository needs to be rewritten and the data storage can no longer utilize IQueryable? So rather than returning this from my repository:
IQueryable<entity> GetEntities();
...and paging the results in my controller, or elsewhere in my application. I instead do this:
IEnumerable<entity> GetEntities_byPage(int page);
...and I do the paging logic in the repository so that it can be translated into an expression at the data source.
I think your repositories should return some fairly tailored data, instead of just a raw data dump that your controller has to clean up (usually after loading it all into memory first, YECK!).
The way I have used the Repository pattern in the past, is just as a very thin mediator between the persistance provider and the data objects - each repository only contains very generic methods (i.e. typically Add/Update/Delete).
I think the business logic in your scenario, i.e. CreateFurBall() should be using the repository, but not be a method exposed by it.