Entity Framework Include with Func next

I defined an Include with Func.

Cool. But what about Include("Products.Order_Details")?

Indeed my Include can only take one relationship level.

So I change my code like this:

public static class ObjectQueryExtension

{

    public static ObjectQuery<T> Include<T>(this ObjectQuery<T> mainQuery, Expression<Func<T, object>> subSelector)

    {

        return mainQuery.Include(FuncToString(subSelector.Body));

    }

    private static string FuncToString(Expression selector)

    {

        switch (selector.NodeType)

        {

            case ExpressionType.MemberAccess:

                return ((selector as MemberExpression).Member as Reflection.PropertyInfo).Name;

            case ExpressionType.Call:

                var method = selector as MethodCallExpression;

                return FuncToString(method.Arguments[0]) + "." + FuncToString(method.Arguments[1]);

            case ExpressionType.Quote:

                return FuncToString(((selector as UnaryExpression).Operand as LambdaExpression).Body);

        }

        throw new InvalidOperationException();

    }

    public static K Include<T, K>(this EntityCollection<T> mainQuery, Expression<Func<T, object>> subSelector)

        where T : EntityObject, IEntityWithRelationships

        where K : class

    {

        return null;

    }

    public static K Include<T, K>(this T mainQuery, Expression<Func<T, object>> subSelector)

        where T : EntityObject

        where K : class

    {

        return null;

    }

}

and I can now do this:

context.Categories.Include(ca => ca.Products.Include<Products, Order_Details>(p => p.Order_Details).Include<Order_Details, Orders>(od => od.Orders))

Isn't it cool?

Published Fri, Jun 6 2008 16:49 by Matthieu MEZIL

Comments

# re: Entity Framework Include with Func next

Absolutely incredible! I don't know what else to say

Tuesday, August 26, 2008 2:04 PM by Mike L

# re: Entity Framework Include with Func next

Thanks Big Smile

Tuesday, August 26, 2008 2:09 PM by Matthieu MEZIL

# Entity Framework Include with Func

Tuesday, April 21, 2009 4:49 PM by Jiří {x2} Činčura

# re: Entity Framework Include with Func next

Very cool!  I also hate using strings in this context: it seems counterintuitive, and very susceptible to mistakes.  At the same time, I'm not sure I'll be using this method.  Which of the following is easier for the next guy looking at my code to understand?

           Room room = ctx.Room

               .Include("Sessions.User")

               .Include("Sessions.Whiteboards.Owner")

               .Include("Sessions.Whiteboards.WhiteboardShape")

               .Include("Sessions.MediaStreams")

               .Include("Owner")

               .FirstOrDefault(r => r.OwnerID == ownerUserID && r.Name == roomName);

           Room room2 = ctx.Room

               .Include(r => r.Sessions.Include<Session, User>(s => s.User))

               .Include(r => r.Sessions.Include<Session, Whiteboard>(s => s.Whiteboards).Include<Whiteboard, User>(w => w.Owner))

               .Include(r => r.Sessions.Include<Session, Whiteboard>(s => s.Whiteboards).Include<Whiteboard, WhiteboardShape>(w => w.WhiteboardShape))

               .Include(r => r.Sessions.Include<Session, MediaStream>(s => s.MediaStreams))

               .Include(r => r.Owner)

               .FirstOrDefault(r => r.OwnerID == ownerUserID && r.Name == roomName);

They both do the same thing, but it requires a great deal more effort to understand what the second one is doing.  I don't like the first way at all -- but the second way is, if anything, uglier and more complicated.

That's not to say I don't appreciate the code -- I very much do!  You're trying to solve a problem that MS really should have solved itself.  There just doesn't seem to be an easy way to solve it.

Does anyone know if MS has addressed this in .NET 4.0?

Tuesday, July 21, 2009 7:33 PM by Ken Smith

# re: Entity Framework Include with Func next

@Ken, I too wish we had addressed this in .NET 4.0, but unfortunately it didn’t climb to the top of the priority list as we were implementing other features (i.e. POCO support, functions exposed in LINQ, model defined functions, T4 integration, FK support, Contains, DefaultIfEmpty, Single/First/OrDefault, better stored procedure support, ExecuteStoreQuery/Translate, OrderBy Lifting, improvements for StartsWith, optimizations for non-unicode columns, EntityDataSource improvements including LINQ support, etc).

It is hard to get any new feature in for .NET 4.0 at this point, but I promise I will bring it up for the next version.

Thursday, July 23, 2009 3:39 PM by Diego Vega

# re: Entity Framework Include with Func next

Thanks a lot Diego

Thursday, July 23, 2009 3:47 PM by Matthieu MEZIL

# re: Entity Framework Include with Func next

I thinkk this is better:

public static ObjectQuery<T,K> Include<T>(this ObjectQuery<T> mainQuery, Expression<Func<T, K>> subSelector)

   {

var sb = new StringBuilder();

       FuncToString(sb, keyExpression.Body);

       return mainQuery.Include(sb.ToString());

   }

       private static void FuncToString(StringBuilder sb, Expression selector)

       {

           switch (selector.NodeType)

           {

               case ExpressionType.Parameter:

//                    sb.Append(((ParameterExpression) selector).Name);

                   return;

               case ExpressionType.MemberAccess:

                   FuncToString(sb, ((MemberExpression) selector).Expression);

                   sb.Append(".");

                   sb.Append(((MemberExpression) selector).Member.Name);

                   return;

           }

           throw new InvalidOperationException();

       }

And now you can use like this:

query.Include(c=>c.Session)

.Incude(c=>c.Session.User)

:)

Thursday, September 17, 2009 7:53 AM by Kamil

# re: Entity Framework Include with Func next

Hi

the problem with your solution is with collection : customers.Include("Orders.OrderDetails")

That's why I did it like this

Matthieu

Thursday, September 17, 2009 8:05 AM by Matthieu MEZIL

# re: Entity Framework Include with Func next

Hello,

Thanks a lot for this code.

I was looking for something like that since I do not want to have strings for names sitting there too.

Now, I only have a strange problem: When I build a query and .Include it passes the data to the FuncToString routine as a ExpressionType.Convert (10) and not one of the three defined to work with.

I added another line to the case section, like this

Case ExpressionType.Convert

Return TryCast(TryCast(TryCast(selector, UnaryExpression).Operand, MemberExpression).Member, Reflection.PropertyInfo).Name (VB Syntax)

which is exactly the same as the .MemberAccess case except for another TryCase selector to UnaryExpression first.

I have no idea what I am doing there, how why what when, but it seems to work. Has anybody a hint why this change is needed, or what I was doing wrong in the first place? Why do I end up with ExpressionType Convert??

I have a second far harder question too: If you have two entities mapped m:n and the middle table of the database does not appear in your entity model (I like that...) I cannot get the function to work at all.

Any hint on that?

Thanks a lot!

Ralf

Thursday, October 22, 2009 3:50 AM by Ralf

# re: Entity Framework Include with Func next

Try with DirectCast instead of TryCast. It was stupid in my case to use the as operator instead a direct cast.

Sunday, November 08, 2009 9:08 AM by Matthieu MEZIL

# Un pattern şi trei implementări (partea 2)

După *** spuneam în postul precedent , fiecare O/RM are propria metodă de a descrie graful de obiecte

Sunday, November 15, 2009 8:27 AM by Tudor Turcu - blog

Leave a Comment

(required) 
(required) 
(optional)
(required)