Print Page | Close Window

Server side query for nested entities - expression instead of string

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2012
Forum Discription: For .NET 4.5
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=4305
Printed Date: 06-Sep-2025 at 7:22am


Topic: Server side query for nested entities - expression instead of string
Posted By: zbig
Subject: Server side query for nested entities - expression instead of string
Date Posted: 07-Sep-2013 at 2:34pm
Is it possible to use expression instead of string with nested entities,
for example:

var usersQuery = entityManager.GetQuery<User>()
.Include(ur => ur.UserRoles)
.Include(ur => ur.UserRoles.Select(r => r.Role))

instead of:

var usersQuery = entityManager.GetQuery<User>()
.Include(ur => ur.UserRoles)
.Include("UserRoles.Role")

This first "style" I have previously used in onother project but with DF it does not work (parsing error ...).





Replies:
Posted By: sbelini
Date Posted: 09-Sep-2013 at 2:48pm
Hi Zbig,

In the situation where you are including entities related to entities in a RelatedEntityList, the option is to use the string parameter.

If including entities related to one entity, then you can use lambda and .PathFor as well.

Note that you cannot use .Select.

You will find more information on including related entities at http://drc.ideablade.com/devforce-2012/bin/view/Documentation/include-related-entities - http://drc.ideablade.com/devforce-2012/bin/view/Documentation/include-related-entities .


Posted By: cefernan
Date Posted: 10-Sep-2013 at 7:12am
Zbig,

Instead of use strings and to prevent runtime error, I've created these extensions methods:
public static IFetchOptions<T> Include<T>(this IFetchOptions<T> source, params string[] attachedPropertyPaths)
{
    return source.Include(IncludeHelper.GetPropertyPath(attachedPropertyPaths));
}
 
public static IFetchOptions<T> Include<T>(this IFetchOptions<T> source, Expression<Func<T, object>> expr, params string[] attachedPropertyPaths)
{
    return source.Include(IncludeHelper.GetPropertyPath(expr, attachedPropertyPaths));
}
How to use:
IncludeExpression = c => c.Include(f => f.FilterCategory)
    .Include(f => f.FilterOperatorClauses)
    .Include(f => f.FilterOperatorClauses, FilterOperatorClause.EntityPropertyNames.FilterConditions)
    .Include(f => f.FilterOperatorClauses, FilterOperatorClause.EntityPropertyNames.FilterConditions, FilterCondition.EntityPropertyNames.FilterConditionValues)
I hope this may help you.


Posted By: cefernan
Date Posted: 10-Sep-2013 at 7:13am
    public static class IncludeHelper
    {
        public static string GetPropertyPath<T>(Expression<Func<T, object>> expr, params string[] attachedPropertyPaths)
        {
            // Build path list
            var body = expr.Body;
            var pathList = new List<string>();
            while (body != null && body.NodeType == ExpressionType.MemberAccess)
            {
                var memberBody = (MemberExpression)body;
                pathList.Insert(0, memberBody.Member.Name);
 
                if (memberBody.Expression.NodeType == ExpressionType.MemberAccess)
                    body = memberBody.Expression;
                else
                    body = null;
            }
 
            // Add path includes to path list
            if (attachedPropertyPaths != null)
                pathList.AddRange(attachedPropertyPaths);
 
            // Build property path
            return String.Join(".", pathList);
        }
 
        public static string GetPropertyPath(params string[] attachedPropertyPaths)
        {
            return String.Join(".", attachedPropertyPaths);
        }
    }


Posted By: stephenmcd1
Date Posted: 10-Sep-2013 at 10:47am
I've built a helper class that builds strings such as 'UserRoles.Role' using strongly typed lambdas.  It's not always the easiest to use but it gets the job done.  And for us, a little bit of annoyance/verbosity when first writing the code is worth it if it saves of from running into problems if the model changes.  An example usage of the helper class would be:
    [TestMethod]
    public void TestBuildPath()
    {
        var actualPath = IncludeHelper
            .BuildPathFor<User>()
            .IncludeMany(user => user.UserRoles)
            .Include(userRole => userRole.Role)
            .ToString();

        Assert.AreEqual("UserRoles.Role", actualPath);

    }

In this case, the IncludeMany method is the one that is really giving us value because it lets us 'flatten' the collection.

You can get the full code from here:   http://gist.github.com/stephenmcd1/5586462 - https://gist.github.com/stephenmcd1/5586462

Note: A very similar question was asked before.  This answer is almost identical to http://www.ideablade.com/forum/forum_posts.asp?TID=4150&PID=16342&title=optionsinclude-of-navigation-property-collections#16342 - the one I posted there .


Posted By: zbig
Date Posted: 10-Sep-2013 at 1:15pm
@sbelini - thanks for the suggestion, good to know, that "PathFor" clause exists.

@cefernan, @stephenmcd1 - thanks for inspiring solutions!
Unfortunatelly I can't use the first one, because I'm not using Cocktail (no IFetchOptions).
I have tried the second one and it works great!

Thanks a lot!



Print Page | Close Window