예제 #1
0
        public static IBuildContext BuildAssociationInline(ExpressionBuilder builder, BuildInfo buildInfo, TableBuilder.TableContext tableContext,
                                                           AccessorMember onMember, AssociationDescriptor descriptor, bool inline, ref bool isOuter)
        {
            var elementType     = descriptor.GetElementType(builder.MappingSchema);
            var parentExactType = descriptor.GetParentElementType();

            var queryMethod = CreateAssociationQueryLambda(
                builder, onMember, descriptor, tableContext.OriginalType, parentExactType, elementType,
                inline, isOuter, tableContext.LoadWith, out isOuter);

            var parentRef = new ContextRefExpression(queryMethod.Parameters[0].Type, tableContext);
            var body      = queryMethod.GetBody(parentRef);

            var context = builder.BuildSequence(new BuildInfo(tableContext, body, new SelectQuery()));

            var tableSource = tableContext.SelectQuery.From.Tables.First();
            var join        = new SqlFromClause.Join(isOuter ? JoinType.OuterApply : JoinType.CrossApply, context.SelectQuery,
                                                     descriptor.GenerateAlias(), true, null);

            tableSource.Joins.Add(join.JoinedTable);

            return(new AssociationContext(builder, descriptor, tableContext, context, join.JoinedTable));
        }
예제 #2
0
        static void BuildJoin(
            ExpressionBuilder builder,
            SqlFromClause.Join join,
            IBuildContext outerKeyContext, Expression outerKeySelector,
            IBuildContext innerKeyContext, Expression innerKeySelector)
        {
            var predicate = builder.ConvertObjectComparison(
                ExpressionType.Equal,
                outerKeyContext, outerKeySelector,
                innerKeyContext, innerKeySelector);

            if (predicate == null)
            {
                predicate = new SqlPredicate.ExprExpr(
                    builder.ConvertToSql(outerKeyContext, outerKeySelector),
                    SqlPredicate.Operator.Equal,
                    builder.ConvertToSql(innerKeyContext, innerKeySelector));

                predicate = builder.Convert(outerKeyContext, predicate);
            }

            join.JoinedTable.Condition.Conditions.Add(new SqlCondition(false, predicate));
        }
예제 #3
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var outerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0], buildInfo.SelectQuery));
            var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery()));

            outerContext = new SubQueryContext(outerContext);
            innerContext = new SubQueryContext(innerContext);

            var selector = (LambdaExpression)methodCall.Arguments[methodCall.Arguments.Count - 1].Unwrap();

            outerContext.SetAlias(selector.Parameters[0].Name);
            innerContext.SetAlias(selector.Parameters[1].Name);

            JoinType joinType;
            var      conditionIndex = 2;

            switch (methodCall.Method.Name)
            {
            case "InnerJoin": joinType = JoinType.Inner; break;

            case "CrossJoin": joinType = JoinType.Inner; conditionIndex = -1; break;

            case "LeftJoin": joinType = JoinType.Left;  break;

            case "RightJoin": joinType = JoinType.Right; break;

            case "FullJoin": joinType = JoinType.Full;  break;

            default:
                conditionIndex = 3;

                var joinValue = (SqlJoinType)methodCall.Arguments[2].EvaluateExpression();

                switch (joinValue)
                {
                case SqlJoinType.Inner: joinType = JoinType.Inner; break;

                case SqlJoinType.Left: joinType = JoinType.Left;  break;

                case SqlJoinType.Right: joinType = JoinType.Right; break;

                case SqlJoinType.Full: joinType = JoinType.Full;  break;

                default: throw new ArgumentOutOfRangeException();
                }

                break;
            }

            if (conditionIndex != -1)
            {
                var condition     = (LambdaExpression)methodCall.Arguments[conditionIndex].Unwrap();
                var conditionExpr = builder.ConvertExpression(condition.Body.Unwrap());

                var join = new SqlFromClause.Join(joinType, innerContext.SelectQuery, null, false,
                                                  Array <SqlFromClause.Join> .Empty);

                outerContext.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);

                builder.BuildSearchCondition(
                    new ExpressionContext(null, new[] { outerContext, innerContext }, condition),
                    conditionExpr,
                    join.JoinedTable.Condition.Conditions,
                    false);
            }
            else
            {
                outerContext.SelectQuery.From.Table(innerContext.SelectQuery);
            }

            return(new SelectContext(buildInfo.Parent, selector, outerContext, innerContext)
#if DEBUG
            {
                MethodCall = methodCall
            }
#endif
                   );
        }
예제 #4
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var outerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery()));

            JoinType joinType;
            var      conditionIndex = 2;

            switch (methodCall.Method.Name)
            {
            case "InnerJoin": joinType = JoinType.Inner; break;

            case "CrossJoin": joinType = JoinType.Inner; conditionIndex = -1; break;

            case "LeftJoin": joinType = JoinType.Left;  break;

            case "RightJoin": joinType = JoinType.Right; break;

            case "FullJoin": joinType = JoinType.Full;  break;

            default:
                conditionIndex = 3;

                joinType = (SqlJoinType)methodCall.Arguments[2].EvaluateExpression() !switch
                {
                    SqlJoinType.Inner => JoinType.Inner,
                    SqlJoinType.Left => JoinType.Left,
                    SqlJoinType.Right => JoinType.Right,
                    SqlJoinType.Full => JoinType.Full,
                    _ => throw new InvalidOperationException($"Unexpected join type: {(SqlJoinType)methodCall.Arguments[2].EvaluateExpression()!}")
                };
                break;
            }

            if (joinType == JoinType.Right || joinType == JoinType.Full)
            {
                outerContext = new DefaultIfEmptyBuilder.DefaultIfEmptyContext(buildInfo.Parent, outerContext, null);
            }
            outerContext = new SubQueryContext(outerContext);


            if (joinType == JoinType.Left || joinType == JoinType.Full)
            {
                innerContext = new DefaultIfEmptyBuilder.DefaultIfEmptyContext(buildInfo.Parent, innerContext, null);
            }
            innerContext = new SubQueryContext(innerContext);

            var selector = (LambdaExpression)methodCall.Arguments[methodCall.Arguments.Count - 1].Unwrap();

            outerContext.SetAlias(selector.Parameters[0].Name);
            innerContext.SetAlias(selector.Parameters[1].Name);

            var joinContext = new JoinContext(buildInfo.Parent, selector, outerContext, innerContext)
#if DEBUG
            {
                Debug_MethodCall = methodCall
            }
#endif
            ;

            if (conditionIndex != -1)
            {
                var condition     = (LambdaExpression)methodCall.Arguments[conditionIndex].Unwrap();
                var conditionExpr = condition.GetBody(selector.Parameters[0], selector.Parameters[1]);

                conditionExpr = builder.ConvertExpression(conditionExpr);

                var join = new SqlFromClause.Join(joinType, innerContext.SelectQuery, null, false,
                                                  Array <SqlFromClause.Join> .Empty);

                outerContext.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);

                builder.BuildSearchCondition(
                    joinContext,
                    conditionExpr,
                    @join.JoinedTable.Condition.Conditions);
            }
            else
            {
                outerContext.SelectQuery.From.Table(innerContext.SelectQuery);
            }

            return(joinContext);
        }