How to handle one DbContext across multiple repositories?
See original GitHub issueI am using a similar approach than this in a project I am currently working on and experienced the following problem:
The repositories do share the same instance of the database context because usually the DbContext is getting registered as scoped (per request). The add, update and delete methods of the EfRepository class immediately save the changes by calling SaveChangesAsync
on the context.
Couldn’t this lead to confusing behaviour? Lets say someone queries an entity (entity1) from a repository (repository1) . After that he makes a change to that entity (entity1) but does not immediately wants to save it. Now in the same request he wants to update another entity (entity2) from a different repository (repository).
The problem now is that the changes in entity1 automatically get saved, because the current database context is tracking the changes of entity1. From a developers perspective it seems to be confusing because you have never called update on repository1 for entity1.
How do you tackle such a problem?
My solution would be to implement a unit of work pattern, that combines all repositories. Only the unit of work class would contain a Save
method. I think it would be more clear for the developer, because someone would implicitly know, that changes made to entities, that got retrieved from the same unit of work would get saved all together.
In the current version i would consider the automatic save of entity1 a side effect. The developer would need detailed knowledge about the concrete implementation of the repository (Change Tracking in ef core).
Are there any other best practices, that could be used to solve that “problem”? I think disabling change tracking or registering the database context and the repositories as transient would be a bad solution.
Kind regards.
Issue Analytics
- State:
- Created 3 years ago
- Comments:8 (4 by maintainers)
Top GitHub Comments
Hi @mrukas,
Yes, that’s correct. On add/update/delete all changes in the DbContext will be saved. The Unit of Work will explicitly expose the Save method, but if you don’t want to save the rest of the changes, then it won’t fix the issue. On the other hand, you can add SaveChanges method explicitly in the repository as well (not to create additional UoW, since DbContext already doing the same job). And, be aware that no matter from which repository you’re calling it, it still will save all the changes.
In any case, the devs always have to be aware of this. No matter if you’re using UoW or not, if they’re not aware what SaveChanges does under the hood, then there will always be improper usages.
If you actually want to exclude all the other changes, then you would need to flag the changed entities as not modified in the DbContext change tracker before save.
I agree there are problems here but I don’t think they are within the scope of this sample to address as they stand now. It’s a good discussion but I’m closing now for inactivity.