Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query Extension for LINQ

I have some code for strongly typing Includes()'s in linq, like so...

public static ObjectQuery<T> Include<T>(this ObjectQuery<T> mainQuery, Expression<Func<T, object>> subSelector)
    {
        return mainQuery.Include(((subSelector.Body as MemberExpression).Member as System.Reflection.PropertyInfo).Name);
    }

    /// <summary>
    /// Old way: (from dbUser in DataSource.DataContext.Users.Include("UserSubscriptions.ChurchSubscriptions") select dbUser);
    /// New way: (from dbUser in DataSource.DataContext.Users.Include<Users, UserSubscriptions>(u => u.UserSubscriptions, s => s.ChurchSubscriptions) select dbUser);
    /// </summary>
    public static ObjectQuery<T> Include<T, Q>(this ObjectQuery<T> mainQuery, Expression<Func<T, object>> tSubSelector, Expression<Func<Q, object>> qSubSelector)
    {
        string tProperty = ((tSubSelector.Body as MemberExpression).Member as System.Reflection.PropertyInfo).Name;
        string qProperty = ((qSubSelector.Body as MemberExpression).Member as System.Reflection.PropertyInfo).Name;
        string path = string.Format("{0}.{1}", tProperty, qProperty);
        return mainQuery.Include(path);
    }

My question is, is there anyway I can write a more generic function account for any level of successive includes? Rather than having to rewrite it for say 3, 4, etc include types?

like image 911
f0ster Avatar asked Nov 06 '22 16:11

f0ster


1 Answers

I guess by successive includes you mean additional sub selectors.

If so, then the following function uses a parameter array for the additional sub selectors (after the first one) while maintaining that the first expression is tied to the same type T as the other ones.

public static ObjectQuery<T> Include<T>(this ObjectQuery<T> mainQuery, Expression<Func<T, object>> tSubSelector, params Expression<Func<object, object>>[] subSelectors)
{
    var pathBuilder = new StringBuilder(((PropertyInfo)((MemberExpression)tSubSelector.Body).Member).Name);
    foreach (var selector in subSelectors)
    {
        pathBuilder.Append('.');
        pathBuilder.Append(((PropertyInfo)((MemberExpression)selector.Body).Member).Name);
    }

    return mainQuery.Include(pathBuilder.ToString());
}
like image 137
Thomas Gerstendörfer Avatar answered Nov 14 '22 20:11

Thomas Gerstendörfer