Entity Framework Include method

Include method in Entity Framework has two overloads. One of which takes navigation property as a string. The other one is Include lambda method. The Include Lambda method is an extension method from the namespace System.Data.Entity. In this tutorial, we look at include method, and learn how to load entities from multiple levels and multiple tables.

The sample database for this example is taken from the AdventureWorks database. Download it and use it to create the model. You can refer to the article code first existing database to reverse engineer the model. Also, you look at the SQL queries that EF generates by logging them to console

Include method

The following example shows how to use the include method against a reference property ProductModel. The EF creates a join statement for each include method and sends it database. Thus retrieving List of Products and its ProductModel in a single query.

using (AdventureWorks db = new AdventureWorks())
{
    //Disable Lazy Loading 
    db.Configuration.LazyLoadingEnabled = false;
    db.Database.Log = Console.Write;

    var product = (from p in db.Products
                    .Include(p => p.ProductModel)  
                    where p.ProductID == 814
                    select p).ToList();

    foreach (var p in product)
    {
        Console.WriteLine("{0} {1} {2}", p.ProductID, p.Name, p.ProductModel.Name);
    }
}

Corresponding SQL

SELECT
    [Extent1].[ProductID] AS [ProductID],
    [Extent1].[Name] AS [Name],
    [Extent1].[ProductNumber] AS [ProductNumber],
    [Extent1].[MakeFlag] AS [MakeFlag],
    [Extent1].[FinishedGoodsFlag] AS [FinishedGoodsFlag],
    [Extent1].[Color] AS [Color],
    [Extent1].[SafetyStockLevel] AS [SafetyStockLevel],
    [Extent1].[ReorderPoint] AS [ReorderPoint],
    [Extent1].[StandardCost] AS [StandardCost],
    [Extent1].[ListPrice] AS [ListPrice],
    [Extent1].[Size] AS [Size],
    [Extent1].[SizeUnitMeasureCode] AS [SizeUnitMeasureCode],
    [Extent1].[WeightUnitMeasureCode] AS [WeightUnitMeasureCode],
    [Extent1].[Weight] AS [Weight],
    [Extent1].[DaysToManufacture] AS [DaysToManufacture],
    [Extent1].[ProductLine] AS [ProductLine],
    [Extent1].[Class] AS [Class],
    [Extent1].[Style] AS [Style],
    [Extent1].[ProductSubcategoryID] AS [ProductSubcategoryID],
    [Extent1].[ProductModelID] AS [ProductModelID],
    [Extent1].[SellStartDate] AS [SellStartDate],
    [Extent1].[SellEndDate] AS [SellEndDate],
    [Extent1].[DiscontinuedDate] AS [DiscontinuedDate],
    [Extent1].[rowguid] AS [rowguid],
    [Extent1].[ModifiedDate] AS [ModifiedDate],
    [Extent2].[ProductModelID] AS [ProductModelID1],
    [Extent2].[Name] AS [Name1],
    [Extent2].[CatalogDescription] AS [CatalogDescription],
    [Extent2].[Instructions] AS [Instructions],
    [Extent2].[rowguid] AS [rowguid1],
    [Extent2].[ModifiedDate] AS [ModifiedDate1]
    FROM  [Production].[Product] AS [Extent1]
    LEFT OUTER JOIN [Production].[ProductModel] AS [Extent2] ON [Extent1].[ProductModelID] = [Extent2].[ProductModelID]
    WHERE 814 = [Extent1].[ProductID]

Include a Collection Property

The Products is collection navigation property for the ProductModel.

using (AdventureWorks db = new AdventureWorks())
{
    //Disable Lazy Loading 
    db.Configuration.LazyLoadingEnabled = false;
    db.Database.Log = Console.Write;

    var models = (from p in db.ProductModels
                    .Include(p => p.Products) 
                    where p.Name == "Classic Vest"
                    select p).ToList();

    foreach (var p in models)
    {
        Console.WriteLine("{0}", p.Name);

        foreach (var product in p.Products)
        {
             Console.WriteLine("\t\t{0} {1}", product.ProductID, product.Name);
        }
    }
}
SELECT
    [Project1].[ProductModelID] AS [ProductModelID],
    [Project1].[Name] AS [Name],
    [Project1].[CatalogDescription] AS [CatalogDescription],
    [Project1].[Instructions] AS [Instructions],
    [Project1].[rowguid] AS [rowguid],
    [Project1].[ModifiedDate] AS [ModifiedDate],
    [Project1].[C1] AS [C1],
    [Project1].[ProductID] AS [ProductID],
    [Project1].[Name1] AS [Name1],
    [Project1].[ProductNumber] AS [ProductNumber],
    [Project1].[MakeFlag] AS [MakeFlag],
    [Project1].[FinishedGoodsFlag] AS [FinishedGoodsFlag],
    [Project1].[Color] AS [Color],
    [Project1].[SafetyStockLevel] AS [SafetyStockLevel],
    [Project1].[ReorderPoint] AS [ReorderPoint],
    [Project1].[StandardCost] AS [StandardCost],
    [Project1].[ListPrice] AS [ListPrice],
    [Project1].[Size] AS [Size],
    [Project1].[SizeUnitMeasureCode] AS [SizeUnitMeasureCode],
    [Project1].[WeightUnitMeasureCode] AS [WeightUnitMeasureCode],
    [Project1].[Weight] AS [Weight],
    [Project1].[DaysToManufacture] AS [DaysToManufacture],
    [Project1].[ProductLine] AS [ProductLine],
    [Project1].[Class] AS [Class],
    [Project1].[Style] AS [Style],
    [Project1].[ProductSubcategoryID] AS [ProductSubcategoryID],
    [Project1].[ProductModelID1] AS [ProductModelID1],
    [Project1].[SellStartDate] AS [SellStartDate],
    [Project1].[SellEndDate] AS [SellEndDate],
    [Project1].[DiscontinuedDate] AS [DiscontinuedDate],
    [Project1].[rowguid1] AS [rowguid1],
    [Project1].[ModifiedDate1] AS [ModifiedDate1]
    FROM ( SELECT
        [Extent1].[ProductModelID] AS [ProductModelID],
        [Extent1].[Name] AS [Name],
        [Extent1].[CatalogDescription] AS [CatalogDescription],
        [Extent1].[Instructions] AS [Instructions],
        [Extent1].[rowguid] AS [rowguid],
        [Extent1].[ModifiedDate] AS [ModifiedDate],
        [Extent2].[ProductID] AS [ProductID],
        [Extent2].[Name] AS [Name1],
        [Extent2].[ProductNumber] AS [ProductNumber],
        [Extent2].[MakeFlag] AS [MakeFlag],
        [Extent2].[FinishedGoodsFlag] AS [FinishedGoodsFlag],
        [Extent2].[Color] AS [Color],
        [Extent2].[SafetyStockLevel] AS [SafetyStockLevel],
        [Extent2].[ReorderPoint] AS [ReorderPoint],
        [Extent2].[StandardCost] AS [StandardCost],
        [Extent2].[ListPrice] AS [ListPrice],
        [Extent2].[Size] AS [Size],
        [Extent2].[SizeUnitMeasureCode] AS [SizeUnitMeasureCode],
        [Extent2].[WeightUnitMeasureCode] AS [WeightUnitMeasureCode],
        [Extent2].[Weight] AS [Weight],
        [Extent2].[DaysToManufacture] AS [DaysToManufacture],
        [Extent2].[ProductLine] AS [ProductLine],
        [Extent2].[Class] AS [Class],
        [Extent2].[Style] AS [Style],
        [Extent2].[ProductSubcategoryID] AS [ProductSubcategoryID],
        [Extent2].[ProductModelID] AS [ProductModelID1],
        [Extent2].[SellStartDate] AS [SellStartDate],
        [Extent2].[SellEndDate] AS [SellEndDate],
        [Extent2].[DiscontinuedDate] AS [DiscontinuedDate],
        [Extent2].[rowguid] AS [rowguid1],
        [Extent2].[ModifiedDate] AS [ModifiedDate1],
        CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
        FROM  [Production].[ProductModel] AS [Extent1]
        LEFT OUTER JOIN [Production].[Product] AS [Extent2] ON [Extent1].[ProductModelID] = [Extent2].[ProductModelID]
        WHERE N'Classic Vest' = [Extent1].[Name]
    )  AS [Project1]
    ORDER BY [Project1].[ProductModelID] ASC, [Project1].[C1] ASC

Filter the child collection

The Include does not allow us to filter the child collection

Include from Multiple Tables

In the following example we have three tables in the include method. Note that all are reference properties.

using (AdventureWorks db = new AdventureWorks())
{
    //Disable Lazy Loading 
    db.Configuration.LazyLoadingEnabled = false;
    db.Database.Log = Console.Write;

    var product = (from p in db.Products
                    .Include(p => p.ProductModel)
                    .Include(p => p.ProductSubcategory)
                    .Include(p=> p.UnitMeasure)
                    where p.UnitMeasure != null
                    select p).Take(5).ToList();

    foreach (var p in product)
    {
        Console.WriteLine("{0} {1} {2} {3} {4}", p.ProductID, p.Name, p.ProductModel.Name, p.ProductSubcategory.Name, p.UnitMeasure.Name);
    }
}
SELECT TOP (5)
    [Extent1].[ProductID] AS [ProductID],
    [Extent1].[Name] AS [Name],
    [Extent1].[ProductNumber] AS [ProductNumber],
    [Extent1].[MakeFlag] AS [MakeFlag],
    [Extent1].[FinishedGoodsFlag] AS [FinishedGoodsFlag],
    [Extent1].[Color] AS [Color],
    [Extent1].[SafetyStockLevel] AS [SafetyStockLevel],
    [Extent1].[ReorderPoint] AS [ReorderPoint],
    [Extent1].[StandardCost] AS [StandardCost],
    [Extent1].[ListPrice] AS [ListPrice],
    [Extent1].[Size] AS [Size],
    [Extent1].[SizeUnitMeasureCode] AS [SizeUnitMeasureCode],
    [Extent1].[WeightUnitMeasureCode] AS [WeightUnitMeasureCode],
    [Extent1].[Weight] AS [Weight],
    [Extent1].[DaysToManufacture] AS [DaysToManufacture],
    [Extent1].[ProductLine] AS [ProductLine],
    [Extent1].[Class] AS [Class],
    [Extent1].[Style] AS [Style],
    [Extent1].[ProductSubcategoryID] AS [ProductSubcategoryID],
    [Extent1].[ProductModelID] AS [ProductModelID],
    [Extent1].[SellStartDate] AS [SellStartDate],
    [Extent1].[SellEndDate] AS [SellEndDate],
    [Extent1].[DiscontinuedDate] AS [DiscontinuedDate],
    [Extent1].[rowguid] AS [rowguid],
    [Extent1].[ModifiedDate] AS [ModifiedDate],
    [Extent2].[ProductModelID] AS [ProductModelID1],
    [Extent2].[Name] AS [Name1],
    [Extent2].[CatalogDescription] AS [CatalogDescription],
    [Extent2].[Instructions] AS [Instructions],
    [Extent2].[rowguid] AS [rowguid1],
    [Extent2].[ModifiedDate] AS [ModifiedDate1],
    [Extent3].[ProductSubcategoryID] AS [ProductSubcategoryID1],
    [Extent3].[ProductCategoryID] AS [ProductCategoryID],
    [Extent3].[Name] AS [Name2],
    [Extent3].[rowguid] AS [rowguid2],
    [Extent3].[ModifiedDate] AS [ModifiedDate2],
    [Extent4].[UnitMeasureCode] AS [UnitMeasureCode],
    [Extent4].[Name] AS [Name3],
    [Extent4].[ModifiedDate] AS [ModifiedDate3]
    FROM    [Production].[Product] AS [Extent1]
    LEFT OUTER JOIN [Production].[ProductModel] AS [Extent2] ON [Extent1].[ProductModelID] = [Extent2].[ProductModelID]
    LEFT OUTER JOIN [Production].[ProductSubcategory] AS [Extent3] ON [Extent1].[ProductSubcategoryID] = [Extent3].[ProductSubcategoryID]
    LEFT OUTER JOIN [Production].[UnitMeasure] AS [Extent4] ON [Extent1].[SizeUnitMeasureCode] = [Extent4].[UnitMeasureCode]
    WHERE [Extent1].[SizeUnitMeasureCode] IS NOT NULL

Include method Multiple Levels

You can also load entities to multiple levels using the following syntax. The include statement includes bothEmployee and Person table (note that both are reference types). The Query will use join to bring data from both the tables as shown below

using (AdventureWorks db = new AdventureWorks())
{
    //Disable Lazy Loading 
    db.Configuration.LazyLoadingEnabled = false;
    db.Database.Log = Console.Write;

    var person = (from p in db.SalesPersons
                    .Include(p => p.Employee.Person)
                    select p).Take(5).ToList();

    foreach (var p in person)
    {
        Console.WriteLine("{0}", p.Employee.Person.FirstName);
    }
}
SELECT TOP (5)
    [Extent1].[BusinessEntityID] AS [BusinessEntityID],
    [Extent1].[TerritoryID] AS [TerritoryID],
    [Extent1].[SalesQuota] AS [SalesQuota],
    [Extent1].[Bonus] AS [Bonus],
    [Extent1].[CommissionPct] AS [CommissionPct],
    [Extent1].[SalesYTD] AS [SalesYTD],
    [Extent1].[SalesLastYear] AS [SalesLastYear],
    [Extent1].[rowguid] AS [rowguid],
    [Extent1].[ModifiedDate] AS [ModifiedDate],
    [Extent2].[BusinessEntityID] AS [BusinessEntityID1],
    [Extent2].[NationalIDNumber] AS [NationalIDNumber],
    [Extent2].[LoginID] AS [LoginID],
    [Extent2].[OrganizationLevel] AS [OrganizationLevel],
    [Extent2].[JobTitle] AS [JobTitle],
    [Extent2].[BirthDate] AS [BirthDate],
    [Extent2].[MaritalStatus] AS [MaritalStatus],
    [Extent2].[Gender] AS [Gender],
    [Extent2].[HireDate] AS [HireDate],
    [Extent2].[SalariedFlag] AS [SalariedFlag],
    [Extent2].[VacationHours] AS [VacationHours],
    [Extent2].[SickLeaveHours] AS [SickLeaveHours],
    [Extent2].[CurrentFlag] AS [CurrentFlag],
    [Extent2].[rowguid] AS [rowguid1],
    [Extent2].[ModifiedDate] AS [ModifiedDate1],
    [Join2].[BusinessEntityID1] AS [BusinessEntityID2],
    [Join2].[PersonType] AS [PersonType],
    [Join2].[NameStyle] AS [NameStyle],
    [Join2].[Title] AS [Title],
    [Join2].[FirstName] AS [FirstName],
    [Join2].[MiddleName] AS [MiddleName],
    [Join2].[LastName] AS [LastName],
    [Join2].[Suffix] AS [Suffix],
    [Join2].[EmailPromotion] AS [EmailPromotion],
    [Join2].[AdditionalContactInfo] AS [AdditionalContactInfo],
    [Join2].[Demographics] AS [Demographics],
    [Join2].[rowguid1] AS [rowguid2],
    [Join2].[ModifiedDate1] AS [ModifiedDate2]
    FROM   [Sales].[SalesPerson] AS [Extent1]
    INNER JOIN [HumanResources].[Employee] AS [Extent2] ON [Extent1].[BusinessEntityID] = [Extent2].[BusinessEntityID]
    LEFT OUTER JOIN  (SELECT [Extent3].[BusinessEntityID] AS [BusinessEntityID1], [Extent3].[PersonType] AS [PersonType], [Extent3].[NameStyle] AS [NameStyle], [Extent3].[Title] AS [Title], [Extent3].[FirstName] AS [FirstName], [Extent3].[MiddleName] AS [MiddleName], [Extent3].[LastName] AS [LastName], [Extent3].[Suffix] AS [Suffix], [Extent3].[EmailPromotion] AS [EmailPromotion], [Extent3].[AdditionalContactInfo] AS [AdditionalContactInfo], [Extent3].[Demographics] AS [Demographics], [Extent3].[rowguid] AS [rowguid1], [Extent3].[ModifiedDate] AS [ModifiedDate1], [Extent4].[BusinessEntityID] AS [BusinessEntityID2]
        FROM  [Person].[Person] AS [Extent3]
        LEFT OUTER JOIN [HumanResources].[Employee] AS [Extent4] ON [Extent3].[BusinessEntityID] = [Extent4].[BusinessEntityID] ) AS [Join2] ON [Extent1].[BusinessEntityID] = [Join2].[BusinessEntityID2]

Summary

In this article, we showed how to make use of the Include method in Entity Framework. The Include Lambda method is an extension method from the namespace System.Data.Entity. Using it we can eagerly load the related entities in a Single Query. We also learned how to load entities from multiple levels and multiple tables.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top