NS.X.
NS.X.

Reputation: 2142

Entity Framework eager loading/"IncludeEverything()"?

In EF4, I have a small object map and the volume of data is also small. So for queries I want to eager load all associated data. Is there any single method call that can do the job, like "IQueryable.IncludeEverything()", rather than call Include() repeatedly with hardcoded property names?

Upvotes: 2

Views: 429

Answers (1)

Andriy Svyryd
Andriy Svyryd

Reputation: 2041

There's nothing out of the box, but you could use MetadataWorkspace to implement it:

    public static IQueryable<T> IncludeEverything<T>(this IQueryable<T> query, ObjectContext context)
        where T : class
    {
        var ospaceEntityType = context.MetadataWorkspace.GetItem<EntityType>(
            typeof(T).FullName, DataSpace.OSpace);

        var cspaceEntityType = context.MetadataWorkspace.GetEdmSpaceType(ospaceEntityType);

        var includedTypes = new HashSet<EdmType>();
        includedTypes.Add(cspaceEntityType);

        return IncludeEverything(query, cspaceEntityType as EntityType, "", includedTypes);
    }

    private static IQueryable<T> IncludeEverything<T>(IQueryable<T> query,
        EntityType entity,
        string path,
        HashSet<EdmType> includedTypes)
        where T : class
    {
        foreach (var navigationProperty in entity.NavigationProperties)
        {
            var propertyEdmType = navigationProperty.TypeUsage.EdmType;
            if (includedTypes.Contains(propertyEdmType))
            {
                continue;
            }
            includedTypes.Add(propertyEdmType);

            var propertyCollectionType = propertyEdmType as CollectionType;

            EntityType propertyEntityType;
            if (propertyCollectionType != null)
            {
                propertyEntityType = propertyCollectionType.TypeUsage.EdmType as EntityType;
            } else
            {
                propertyEntityType = propertyEdmType as EntityType;
            }

            var propertyPath = string.IsNullOrEmpty(path) ? "" : path + ".";
            propertyPath += navigationProperty.Name;
            query = query.Include(propertyPath);
            query = IncludeEverything(query, propertyEntityType, propertyPath, includedTypes);
        }

        return query;
    }

Note that this code is just for illustration. It doesn't have parameter validation, it may include the same enities several times and it won't include all the related entities if there are cycles in your model.

Upvotes: 4

Related Questions