You are right, but the rule is more complicated so that it really works as expected. If you define your navigation property virtual , EF at runtime will create a new class (dynamic proxy) derived from your Brand class, and use it instead. This new dynamically created class contains logic for loading the navigation property on first access. This function is called lazy loading (or more transparent lazy loading).
What rules must be followed to complete this work:
- All navigation properties in the class must be
virtual - Cannot disable dynamic proxy creation (
context.Configuration.ProxyCreationEnabled ). It is enabled by default. - Lazy loading should not be disabled (
context.Configuration.LazyLoadingEnabled ). It is enabled by default. - The object must be attached (by default, if you load the object from the database) into the context and the context should not be deleted = lazy loading works only within the context of the life used to load it from the database (or where the proxy object was attached)
The opposite of lazy loading is called impatient loading, and this is what Include does. If you use Include , your navigation property is loaded with the main object.
Using lazy loading and fast loading depends on your needs as well as performance. Include loads all the data in one database query, but can lead to a huge data set when using a large number of inclusions or loading multiple objects. If you are sure that you will need Brand and all Products for processing, you should use active download.
In turn, lazy loading is used if you are not sure which navigation property you will need. For example, if you download 100 brands, but you only need to access products from one brand, there is no need to download products for all brands in the original request. The disadvantage of lazy loading is a separate request (database callback) for each navigation property => if you download 100 brands without inclusion and you get access to the Products property in each Brand instance, your code will generate another 100 requests to fill these properties navigation = loaded download will use only one request, but lazy loading used 101 requests (this is called N + 1 problem).
In more complex scenarios, you may find that none of these strategies work as needed, and you can use either a third strategy called explicit loading, or separate requests to download brands and products for all brands that you need.
Explicit loading has the same disadvantages as lazy loading, but you must start it manually:
context.Entry(brand).Collection(b => b.Products).Load();
The main advantages for explicit loading are the ability to filter the relation. You can use Query() to Load() and use any filtering or even eager loading of nested relationships.
Ladislav Mrnka Oct 12 '11 at 10:51
source share