There are different patterns we can use to load related entities in Entity Framework. Before understanding these patterns, we need to understand the terms associations and navigation properties. This is because loading related entities is done using navigation properties. I recommend that you read the article on how to create an EDM for the Sales Order Management database and then read this article.
Associations specify relationships between Entity Types. Depending on the relationship set in the database, the Entity Data Model wizard creates these associations. Associations specify the entities that are involved in the relationship and their multiplicity. Multiplicity means whether the relationship between two entities is one-to-many or one-to-one or many-to-many. To view the properties of the association, open the model in the designer window and right click on the line between Customer entity and SalesOrder entity. The properties window of the association is displayed as shown in Figure given below.
After we have created the model, the designer window looks like this.
If we right-click on the navigation property Customer of SalesOrder entity, the properties window is displayed as shown in fig: given below.
Observe that in the designer window, the Customer entity contains SalesOrders navigation property. Using this property we can navigate to a related entity, here SalesOrder entity. The picture given below shows the properties window of SalesOrder navigation property. This property returns collection of SalesOrder types. The SalesOrders endpoint is defined in the FK_SalesOrder_Customer association and has a multiplicity of *(Many) and Customer.SalesOrders property returns a collection of SalesOrder entities.
Navigation properties that return collections
The navigation property SalesOrders of Customer entity is a Navigation collection. So, when we use the statement Customer.SalesOrders a collection of SalesOrder entities is returned. The navigation properties either return a collection or a reference. In the second figure, observe that the Customer navigation property returns a Customer reference for a SalesOrder entity.
When we create EDM, depending on the relationships set in the database between tables, associations are created in the model and entities are created with navigation properties at both ends of an association.
As stated earlier, we load related entities using navigation properties. We can follow three different patterns to load related entities in the Entity Framework. They are
What is lazy loading? How to use it to Load Related Objects
- Lazy Loading/deferred loading
- Explicit loading
- Eager loading/Eager fetching
Lazyloading is one of the patterns we use to load related objects using navigation properties without writing an additional query. To understand this concept, we will consider the following example.
In the Sales Order Management Entity Data Model, both customer entity and SalesOrder entity contain navigation properties which were discussed earlier.
Now let us generate a report listing the number of sales orders for each customer. Observe the code given below.
In the code, only one query is used to retrieve all the customers and their related data. We have used navigation property of the Customer entity and retrieved the number of SalesOrders for a Customer. This is called Lazy loading or deferred loading as the main objects Customers are loaded first and related objects that is Sales Orders are loaded later (lazy). Because you are seeing only one query, do not assume that only one query is executed against the database. In fact, whenever a navigation property is accessed, a connection to database is established and a separate query is executed. For example, if the database contains 50 customers, totally 51 queries are executed - 50 round trips to the database to return the number of sales orders for each customer and one query is executed to get all the customer details.
When we use this feature in an application, we should consider the performance issues which arise. Many a times a performance hit is observed. Whenever we use navigation property in .Net4, by default EF performs Lazy loading. It causes many round trips to the database but we can control when the extra round trip to the database should occur. We can disable it by changing the setting of the LazyLoadingEnabled property of the Context. The below code is the default code generated when we create EDM. In the constructor of the Objectcontext, the LazyLoadingEnabled property is set to true by default. We set LazyLoadingEnabled property to false.
When we execute the above code, the number of sales orders returned for each customer will be zero. This is because query will not execute. Now, let us see the second alternative to load related data which is the Explicit Loading pattern.
In this Explicit loading pattern, we tell Entity Framework explicitly about the related entities to be loaded. Observe the below code.
In the given code, the navigation property SalesOrders returns EntityCollection. To explicitly retrieve the related entities from the data source either we use Load method on the EntityCollection or use LoadProperty method of the ObjectContext. However, we cannot use Load methods when we are using POCO classes. We use LoadProperty method of ObjectContext to perform explicit loading with POCOs.
When we use Explicit loading too, a call to the Load method opens a connection to the database to retrieve the related information forcing round trip to the database. But the advantage of using Explicit Loading over Lazy Loading is that we will have more control over related entities to be returned. For example, suppose we want to display every Customer and SalesOrders details for all Customers whose closing balance is greater than 10000. In this situation, if we use explicit loading we will have more control.
Eager loading / Eager fetching
This is the third alternative to access all the related entities with a single query. Sometimes, it is more efficient to retrieve all the related data using Eager loading. We perform Eager loading using Include method. This method is a query builder method and we can apply it on ObjectSet. The statement Context.Customers in the code given below returns the ObjectSet and we can apply Include method on it.
In the code example, we have passed a navigation property - SalesOrders to the Include method. This single query will retrieve all the customers and their sales orders in one go. This is eager loading.
Both Lazy and Explicit loading make multiple trips to the database while Eager Loading pattern retrieves all the related data in a single query. But the amount of data it retrieves is more and it will be a problem in enterprise applications where client application is in a different tier. This is because all the data to be passed to the client tier should be serialized. And so, we need to understand the requirement and then apply the correct pattern when loading related entities.