Esempio n. 1
0
                public Expression GetExpression(Expression parent, AssociatedTableContext association)
                {
                    Expression expr  = null;
                    var        param = Expression.Parameter(typeof(T), "c");

                    foreach (var cond in (association).ParentAssociationJoin.Condition.Conditions)
                    {
                        var p  = (SelectQuery.Predicate.ExprExpr)cond.Predicate;
                        var e1 = Expression.MakeMemberAccess(parent, ((SqlField)p.Expr1).ColumnDescriptor.MemberInfo);

                        Expression e2 = Expression.MakeMemberAccess(param, ((SqlField)p.Expr2).ColumnDescriptor.MemberInfo);

                        while (e1.Type != e2.Type)
                        {
                            if (e1.Type.IsNullable())
                            {
                                e1 = Expression.PropertyOrField(e1, "Value");
                                continue;
                            }

                            if (e2.Type.IsNullable())
                            {
                                e2 = Expression.PropertyOrField(e2, "Value");
                                continue;
                            }

                            e2 = Expression.Convert(e2, e1.Type);
                        }

                        var ex = Expression.Equal(e1, e2);

                        expr = expr == null ? ex : Expression.AndAlso(expr, ex);
                    }

                    var predicate = Expression.Lambda <Func <T, bool> >(expr, param);

                    return(association.Builder.DataContextInfo.DataContext.GetTable <T>().Where(predicate).Expression);
                }
                public Expression GetSubquery(
                    ExpressionBuilder builder,
                    AssociatedTableContext tableContext,
                    ParameterExpression parentObject)
                {
                    var lContext = Expression.Parameter(typeof(IDataContext), "ctx");
                    var lParent  = Expression.Parameter(typeof(object), "parentObject");

                    Expression expression;

                    var queryMethod = tableContext.Association.GetQueryMethod(parentObject.Type, typeof(T));

                    if (queryMethod != null)
                    {
                        var ownerParam = queryMethod.Parameters[0];
                        var dcParam    = queryMethod.Parameters[1];
                        var ownerExpr  = Expression.Convert(lParent, parentObject.Type);

                        expression = queryMethod.Body.Transform(e =>
                                                                e == ownerParam ? ownerExpr : (e == dcParam ? lContext : e));
                    }
                    else
                    {
                        var tableExpression = builder.DataContext.GetTable <T>();

                        var loadWith = tableContext.GetLoadWith();

                        if (loadWith != null)
                        {
                            foreach (var members in loadWith)
                            {
                                var pLoadWith  = Expression.Parameter(typeof(T), "t");
                                var isPrevList = false;

                                Expression obj = pLoadWith;

                                foreach (var member in members)
                                {
                                    if (isPrevList)
                                    {
                                        obj = new GetItemExpression(obj);
                                    }

                                    obj = Expression.MakeMemberAccess(obj, member);

                                    isPrevList = typeof(IEnumerable).IsSameOrParentOf(obj.Type);
                                }

                                tableExpression = tableExpression.LoadWith(Expression.Lambda <Func <T, object> >(obj, pLoadWith));
                            }
                        }

                        // Where
                        var pWhere = Expression.Parameter(typeof(T), "t");

                        Expression expr = null;

                        for (var i = 0; i < tableContext.Association.ThisKey.Length; i++)
                        {
                            var thisProp  = Expression.PropertyOrField(Expression.Convert(lParent, parentObject.Type), tableContext.Association.ThisKey[i]);
                            var otherProp = Expression.PropertyOrField(pWhere, tableContext.Association.OtherKey[i]);

                            var ex = ExpressionBuilder.Equal(tableContext.Builder.MappingSchema, otherProp, thisProp);

                            expr = expr == null ? ex : Expression.AndAlso(expr, ex);
                        }

                        var predicate = tableContext.Association.GetPredicate(parentObject.Type, typeof(T));
                        if (predicate != null)
                        {
                            var ownerParam = predicate.Parameters[0];
                            var childParam = predicate.Parameters[1];
                            var ownerExpr  = Expression.Convert(lParent, parentObject.Type);

                            var body = predicate.Body.Transform(e =>
                                                                e == ownerParam ? ownerExpr : (e == childParam ? pWhere : e));

                            expr = expr == null ? body : Expression.AndAlso(expr, body);
                        }

                        expression = tableExpression.Where(Expression.Lambda <Func <T, bool> >(expr, pWhere)).Expression;
                    }

                    var lambda      = Expression.Lambda <Func <IDataContext, object, IEnumerable <T> > >(expression, lContext, lParent);
                    var queryReader = CompiledQuery.Compile(lambda);

                    expression = Expression.Call(
                        null,
                        MemberHelper.MethodOf(() => ExecuteSubQuery(null, null, null)),
                        ExpressionBuilder.QueryRunnerParam,
                        Expression.Convert(parentObject, typeof(object)),
                        Expression.Constant(queryReader));

                    var memberType = tableContext.Association.MemberInfo.GetMemberType();

                    if (memberType == typeof(T[]))
                    {
                        return(Expression.Call(null, MemberHelper.MethodOf(() => Enumerable.ToArray <T>(null)), expression));
                    }

                    if (memberType.IsSameOrParentOf(typeof(List <T>)))
                    {
                        return(Expression.Call(null, MemberHelper.MethodOf(() => Enumerable.ToList <T>(null)), expression));
                    }

                    var ctor = memberType.GetConstructorEx(new[] { typeof(IEnumerable <T>) });

                    if (ctor != null)
                    {
                        return(Expression.New(ctor, expression));
                    }

                    var l = builder.MappingSchema.GetConvertExpression(expression.Type, memberType, false, false);

                    if (l != null)
                    {
                        return(l.GetBody(expression));
                    }

                    throw new LinqToDBException($"Expected constructor '{memberType.Name}(IEnumerable<{tableContext.ObjectType}>)'");
                }