George Mauer
George Mauer

Reputation: 122062

Eager load all properties with Entity Framework

So LazyLoadingEnabled = false apparently doesn't do what I thought it did. And has next to no documentation.

I design my entity trees very carefully. I think hard about every relationship. When I load up an entity that is an Aggregate Root, I want everything that is navigable to from there to load. That's how the Aggregate root concept works after all, if I want something to be weekly related I'd stick an id on the entity and manage the relationship myself.

Is there a way to do this with Entity Framework?

Upvotes: 1

Views: 720

Answers (2)

Hopeless
Hopeless

Reputation: 4763

You can try obtaining all NavigationProperties of the element type (in IQueryable). By accessing to the MetadataWorkspace of ObjectContext you can get those properties of a specific type and Include all easily.

Note that I suppose you're using EF5 or later version, whereas DbContext is used. We access to ObjectContext via the interface IObjectContextAdapter. Here is the code:

public static IQueryable<T> LoadAllRelatedObjects<T>(this IQueryable<T> source, DbContext context) {
        //obtain the EntityType corresponding to the ElementType first
        //then we can get all NavigationProperties of the ElementType
        var items = (ObjectItemCollection) ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace.GetItemCollection(DataSpace.OSpace);            
        var entityType = items.OfType<EntityType>().Single(e => items.GetClrType(e) == source.ElementType);
        return entityType.NavigationProperties
                         .Aggregate(source, (c, e) => c.Include(e.Name));
}

Note in new version (since EF5), the namespace of ObjectItemCollection (and other metadata items) is System.Data.Entity.Core.Metadata.Edm, while in the old version (before EF5), it's System.Data.Metadata.Emd.

Usage:

yourModel.YourEntities.LoadAllRelatedObjects(yourModel)
         //. more query here ...
         ;

Upvotes: 2

Matthew
Matthew

Reputation: 817

I don't think there's a way to have all of the navigation properties auto-eager load. How about making an extension method instead?

public static IQueryable<Company> LoadCompany(this IQueryable<Company> query) {
     return query.Include(x => x.Divisions)
                 .Include(x => x.Departments)
                 .Include(x => x.Employees);
}

Example:

var query = from company in db.Companies.LoadCompany()
            where company.Name == "Microsoft"
            select company;

Upvotes: 1

Related Questions