EF Code First - Include(x => x.Properties.Entity) a 1 : Many association
Asked Answered
M

3

39

Given a EF-Code First CTP5 entity layout like:

public class Person { ... }

which has a collection of:

public class Address { ... }

which has a single association of:

public class Mailbox { ... }

I want to do:

PersonQuery.Include(x => x.Addresses).Include("Addresses.Mailbox")

WITHOUT using a magic string. I want to do it using a lambda expression.

I am aware what I typed above will compile and will bring back all Persons matching the search criteria with their addresses and each addresses' mailbox eager loaded, but it's in a string which irritates me.

How do I do it without a string?

Thanks Stack!

Mutable answered 1/3, 2011 at 19:56 Comment(0)
T
77

For that you can use the Select method:

PersonQuery.Include(x => x.Addresses.Select(a => a.Mailbox));

You can find other examples in here and here.

Toname answered 1/3, 2011 at 21:27 Comment(1)
Nice use of Select. Never considered that. +1Soccer
A
18

For any one thats still looking for a solution to this, the Lambda includes is part of EF 4+ and it is in the System.Data.Entity namespace; examples here

http://romiller.com/2010/07/14/ef-ctp4-tips-tricks-include-with-lambda/

Alamo answered 16/2, 2012 at 2:35 Comment(0)
J
7

It is described in this post: http://www.thomaslevesque.com/2010/10/03/entity-framework-using-include-with-lambda-expressions/

Edit (By Asker for readability): The part you are looking for is below:

public static class ObjectQueryExtensions
{
    public static ObjectQuery<T> Include<T>(this ObjectQuery<T> query, Expression<Func<T, object>> selector)
    {
        string path = new PropertyPathVisitor().GetPropertyPath(selector);
        return query.Include(path);
    }

    class PropertyPathVisitor : ExpressionVisitor
    {
        private Stack<string> _stack;

        public string GetPropertyPath(Expression expression)
        {
            _stack = new Stack<string>();
            Visit(expression);
            return _stack
                .Aggregate(
                    new StringBuilder(),
                    (sb, name) =>
                        (sb.Length > 0 ? sb.Append(".") : sb).Append(name))
                .ToString();
        }

        protected override Expression VisitMember(MemberExpression expression)
        {
            if (_stack != null)
                _stack.Push(expression.Member.Name);
            return base.VisitMember(expression);
        }

        protected override Expression VisitMethodCall(MethodCallExpression expression)
        {
            if (IsLinqOperator(expression.Method))
            {
                for (int i = 1; i < expression.Arguments.Count; i++)
                {
                    Visit(expression.Arguments[i]);
                }
                Visit(expression.Arguments[0]);
                return expression;
            }
            return base.VisitMethodCall(expression);
        }

        private static bool IsLinqOperator(MethodInfo method)
        {
            if (method.DeclaringType != typeof(Queryable) && method.DeclaringType != typeof(Enumerable))
                return false;
            return Attribute.GetCustomAttribute(method, typeof(ExtensionAttribute)) != null;
        }
    }
}
Journalistic answered 1/3, 2011 at 20:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.