I want to have an understanding of how Entity Framework uses Proxy classes? Why Entity Framework needs Proxy classes? What actually happens behind the scenes when Lazy loading is Enabled?
2 Answers
It's a decorator that adds lazy loading capabilities to an entity object by -
- Storing a reference to the context.
- Overriding navigation properties to make them load when they're accessed, using the context.
The proxy inherits from the entity class. Therefore, the navigation properties must be virtual
and the entity class can't be sealed
.
Maybe the most instructive way of understanding them is by seeing what it takes to implement lazy loading without proxies.

- 105,341
- 31
- 202
- 291
In the old days before POCO
, entity classes in EF inherited from EntityObject. This had some tie-ins to the old ObjectContext
change tracker and such, and could provide (I think) some of the functionality needed to do things like lazy loading of navigation properties.
With the advent of POCO
(plain-old CLR objects), that class inheritance went away. Hence the name. That means that your entity classes have only the code you put in them.
When you write a navigation property, it generally looks something like:
public virtual Course Course { get; set; }
Pretty basic, no getter/setter code. This means by default it's not going to do anything fancy like lazy loading. It doesn't know how.
Enter the proxy/wrapper class: it has code to do things like lazy loading.
I think the main code is EntityProxyFactory and EntityProxyTypeInfo, which appears to create the baseGetter
and baseSetter
expression used by the proxy factory. It's creating the expression using a MethodInfo from the proxy type...I haven't found that code yet...I think that's where the real work is being done.
Also, this is for EF6...the EF core code is in a different repo.
I haven't gotten far enough with the EF code to know if this is exactly what it's doing, but the way you would manually load a navigation property is through the change tracker entry, like this:
using var db = new BloggingContext();
var blog = db.Blogs.First();
// get change tracker entry for blog
var entry = db.Entry(blog);
// load the blog.Posts navigation property
entry.Reference(x=> x.Posts).Load();
// now you can use blog.Posts!
I would guess it's doing something equivalent to this.

- 7,031
- 2
- 22
- 29