Entity Framework, Navigation Properties, and the Repository Pattern

Generic Repository vs Non-generic Repository

Generic repository is not a pattern. Generic repository is just a wrapper. It can be useful for some special scenarios as a base class for specific repositories but in most cases it is just over used and over hyped nonsense.

Navigation properties

Repository itself should be used with aggregate root. The aggregate root is aggregation of multiple related entities where you have repository only for principal because dependencies cannot exist without parent. Repository itself handles loading and persisting all entity types in aggregation.

Even with aggregate roots you will end with some challenges. For example how to handle many-to-many relations? Many to many relation always represent scenario where there is no real principal or dependent entity = they are not in aggregation. If you only set relation between these two entities through navigation property it is still OK but EF also allows you creating related entity through navigation property and it somehow violates repository purpose. You can enforce your repository to test existence of relations but it can cause a lot of additional queries so you will most probably leave it as leaky abstraction of your implementation.

Self-Tracking entities

From your code I think you confused self-tracking entities with attached entities. What you describe is difference between attached and detached entities. If you want to support both scenarios in single code your UpdateEntity method has a meaning because you must test if entity is attached and attach it + set state if not.

Keeping DbContext in sync

This is where you are missing unit of work. Repository itself wraps only queries and storing entities into context but unit of work handles context creation / retireval and persisting changes to database. As example you can take DbSet (EF’s implementation of repository) and DbContext (EF’s implementation of unit of work).

Leave a Comment