VictorStone

导航

 

Entity framework中 include 扩展:

var xList = repository.GetQuery<Site>().Include(s => s.TaskGroups.Select(sd => sd.TaskLists)).ToList<Site>();

如果用实体框架自带的扩展, 请注意添加命名空间System.Data.Entity的引用。

[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
public static IQueryable<T> Include<T, TProperty>(this IQueryable<T> source, Expression<Func<T, TProperty>> path) 
where T : class;

 01.

public static IQueryable<T> Include<T>(this ObjectSet<T> source, Expression<Func<T, object>> path) where T : class
{
    StringBuilder pathBuilder = new StringBuilder();
 
    MemberExpression pro = path.Body as MemberExpression;
    while (pro != null)
    {
        //Exprssion有點像鏈結串列,從Statemant的後方往前連結,如: x=> x.Customer.CustomerAddress
        //path.Body是CustomerAddress
        //CustomerAddress的Expression是Customer
        //Customer的Expression是x
        pathBuilder.Insert(0, "." + pro.Member.Name);
        pro = pro.Expression as MemberExpression;
    }
    return source.Include(pathBuilder.ToString(1, pathBuilder.Length-1));
}

02.

    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;
            }

        }

    }

 最原始的写法:

    // Define a LINQ query with a path that returns 
    // orders and items for a contact.
    var contacts = (from contact in context.Contacts
                  .Include("SalesOrderHeaders.SalesOrderDetails")
                    select contact).FirstOrDefault();

Contacts.SalesOrderHeaders.SaleOrderDetails 将某联系人全部的订单头和明细都列出来了。
posted on 2013-08-16 13:53  VictorStone  阅读(1298)  评论(0编辑  收藏  举报