C#, Entity Framework

How to automatically load navigation properties in Entity Framework

Note: this blog is no longer maintained. Please go here to see the latest updates of this post.

Anyone who has worked with Entity Framework will have had to manage with loading related entities. I believe many developers will agree the way that system works is difficult to reconcile with design patterns such as the Repository pattern. In this post, I’ll provide one quick and easy way to automatically load all related properties from the database.

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public string Tags { get; set; }  

    public ICollection<Post> Posts { get; set; }
}

By default, Entity Framework will load all “simple” types such as integers or string values. On the other, custom types such as the collection of Post objects aren’t in scope by default and will be null.

Of course, there is a method called “Include” that you can use to instruct Entity Framework to load the property with the specified parameter in the object graph:

var allBlogPosts = context.Blogs.Include("Posts").ToList();

You can add as many includes as you want, as long as you provide a property name to its parameter.

This doesn’t work really well if you are planning to implement a generic repository pattern. Because you don’t know the objects you’re working with, you can’t provide the names of your properties, but that’s something you don’t want to know if you’re trying to make something generic.

Instead, I have a code sample that automatically loads all navigation properties to the graph. If one of your requirements is performance, this probably won’t be your answer. If you want to have a comfortable way of accessing fully populate data, this is your answer.


public virtual IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null)
		{
			IQueryable<TEntity> query = where == null ? this.Context.Set<TEntity>() : this.Context.Set<TEntity>().Where(where);

			var workspace = ((IObjectContextAdapter)this.Context).ObjectContext.MetadataWorkspace;
			var itemCollection = (ObjectItemCollection)(workspace.GetItemCollection(DataSpace.OSpace));
			var entityType = itemCollection.OfType<EntityType>().FirstOrDefault(e => itemCollection.GetClrType(e) == typeof(TEntity));

			if(entityType != null)
			{
				foreach (var navigationProperty in entityType.NavigationProperties)
				{
					query = query.Include(navigationProperty.Name);
				}
			}			

			return query;
		}

As you can see, this code sample also uses the Include statement, but it’s retrieving the parameters in runtime. Using the EF API, the current type is inspected and only the properties that are EntityTypes according to EF are included manually in the query.

This code snippet offers some interesting perspectives to make it even more dynamic. Everything you see here is pure Entity Framework, no workarounds or whatsoever, so I like to think this as a sustainable solution.

Advertisements

3 thoughts on “How to automatically load navigation properties in Entity Framework

  1. thanks for this interesting stuff, i wonder if its possible to include also navigation properties of nested navigation properties up to n-th level (or all)?

    Like

    1. You could do this by using recursion. Within the loop you then should check the type, and if it is a complex type, you could run the same code as above (to include the properties). This way you don’t have to rewrite any code or do complex coding. Let me check this as soon as I have some time to investigate this. If you come up with a solution earlier, please get back to me so I can update this post!

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s