Exemplo n.º 1
0
            protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
            {
                var mergeContext = (MergeContext)builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

                var statement = mergeContext.Merge;
                var operation = new SqlMergeOperationClause(MergeOperationType.DeleteBySource);

                statement.Operations.Add(operation);

                var predicate = methodCall.Arguments[1];

                if (!(predicate is ConstantExpression constPredicate) || constPredicate.Value != null)
                {
                    var condition     = (LambdaExpression)predicate.Unwrap();
                    var conditionExpr = builder.ConvertExpression(condition.Body.Unwrap());

                    operation.Where = new SqlSearchCondition();

                    builder.BuildSearchCondition(
                        new ExpressionContext(null, new[] { mergeContext.TargetContext }, condition),
                        conditionExpr,
                        operation.Where.Conditions,
                        false);
                }

                return(mergeContext);
            }
Exemplo n.º 2
0
            protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
            {
                var mergeContext = (MergeContext)builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

                var statement = mergeContext.Merge;

                if (methodCall.Arguments.Count == 2)
                {
                    // On<TTarget, TSource>(IMergeableOn<TTarget, TSource> merge, Expression<Func<TTarget, TSource, bool>> matchCondition)
                    var predicate     = methodCall.Arguments[1];
                    var condition     = (LambdaExpression)predicate.Unwrap();
                    var conditionExpr = builder.ConvertExpression(condition.Body.Unwrap());

                    mergeContext.AddTargetParameter(condition.Parameters[0]);
                    mergeContext.AddSourceParameter(condition.Parameters[1]);

                    builder.BuildSearchCondition(
                        new ExpressionContext(null, new[] { mergeContext.TargetContext, mergeContext.SourceContext }, condition),
                        conditionExpr,
                        statement.On.Conditions,
                        false);
                }
                else if (methodCall.Arguments.Count == 3)
                {
                    var targetKeyLambda = ((LambdaExpression)methodCall.Arguments[1].Unwrap());
                    var sourceKeyLambda = ((LambdaExpression)methodCall.Arguments[2].Unwrap());

                    var targetKeySelector = targetKeyLambda.Body.Unwrap();
                    var sourceKeySelector = sourceKeyLambda.Body.Unwrap();

                    var targetKeyContext = new ExpressionContext(buildInfo.Parent, mergeContext.TargetContext, targetKeyLambda);
                    var sourceKeyContext = new ExpressionContext(buildInfo.Parent, mergeContext.SourceContext, sourceKeyLambda);

                    if (targetKeySelector.NodeType == ExpressionType.New)
                    {
                        var new1 = (NewExpression)targetKeySelector;
                        var new2 = (NewExpression)sourceKeySelector;

                        for (var i = 0; i < new1.Arguments.Count; i++)
                        {
                            var arg1 = new1.Arguments[i];
                            var arg2 = new2.Arguments[i];

                            JoinBuilder.BuildJoin(builder, statement.On, targetKeyContext, arg1, sourceKeyContext, arg2);
                        }
                    }
                    else if (targetKeySelector.NodeType == ExpressionType.MemberInit)
                    {
                        // TODO: migrate unordered members support to original code
                        var mi1 = (MemberInitExpression)targetKeySelector;
                        var mi2 = (MemberInitExpression)sourceKeySelector;

                        if (mi1.Bindings.Count != mi2.Bindings.Count)
                        {
                            throw new LinqException($"List of member inits does not match for entity type '{targetKeySelector.Type}'.");
                        }

                        for (var i = 0; i < mi1.Bindings.Count; i++)
                        {
                            var binding2 = (MemberAssignment)mi2.Bindings.Where(b => b.Member == mi1.Bindings[i].Member).FirstOrDefault();
                            if (binding2 == null)
                            {
                                throw new LinqException($"List of member inits does not match for entity type '{targetKeySelector.Type}'.");
                            }

                            var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression;
                            var arg2 = binding2.Expression;

                            JoinBuilder.BuildJoin(builder, statement.On, targetKeyContext, arg1, sourceKeyContext, arg2);
                        }
                    }
                    else
                    {
                        JoinBuilder.BuildJoin(builder, statement.On, targetKeyContext, targetKeySelector, sourceKeyContext, sourceKeySelector);
                    }
                }
                else
                {
                    // OnTargetKey<TTarget>(IMergeableOn<TTarget, TTarget> merge)
                    var targetType       = methodCall.Method.GetGenericArguments()[0];
                    var pTarget          = Expression.Parameter(targetType, "t");
                    var pSource          = Expression.Parameter(targetType, "s");
                    var targetDescriptor = builder.MappingSchema.GetEntityDescriptor(targetType);

                    Expression?ex = null;

                    for (var i = 0; i < targetDescriptor.Columns.Count; i++)
                    {
                        var column = targetDescriptor.Columns[i];
                        if (!column.IsPrimaryKey)
                        {
                            continue;
                        }

                        var expr = Expression.Equal(
                            Expression.MakeMemberAccess(pTarget, column.MemberInfo),
                            Expression.MakeMemberAccess(pSource, column.MemberInfo));
                        ex = ex != null?Expression.AndAlso(ex, expr) : expr;
                    }

                    if (ex == null)
                    {
                        throw new LinqToDBException("Method OnTargetKey() needs at least one primary key column");
                    }

                    var condition = Expression.Lambda(ex, pTarget, pSource);

                    builder.BuildSearchCondition(
                        new ExpressionContext(null, new[] { mergeContext.TargetContext, mergeContext.SourceContext }, condition),
                        ex,
                        statement.On.Conditions,
                        false);
                }

                mergeContext.SourceContext.MatchBuilt();
                return(mergeContext);
            }
Exemplo n.º 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
                   );
        }
Exemplo n.º 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);
        }
            protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
            {
                var mergeContext = (MergeContext)builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

                var statement = mergeContext.Merge;
                var operation = new SqlMergeOperationClause(MergeOperationType.Insert);

                statement.Operations.Add(operation);

                var predicate = methodCall.Arguments[1];
                var setter    = methodCall.Arguments[2];

                if (!setter.IsNullValue())
                {
                    var setterExpression = (LambdaExpression)setter.Unwrap();
                    mergeContext.AddSourceParameter(setterExpression.Parameters[0]);

                    UpdateBuilder.BuildSetterWithContext(
                        builder,
                        buildInfo,
                        setterExpression,
                        mergeContext.TargetContext,
                        operation.Items,
                        mergeContext.SourceContext);
                }
                else
                {
                    // build setters like QueryRunner.Insert
                    var sqlTable = (SqlTable)statement.Target.Source;
                    var param    = Expression.Parameter(sqlTable.ObjectType, "s");

                    foreach (var field in sqlTable.Fields)
                    {
                        if (field.IsInsertable)
                        {
                            var expression = LinqToDB.Expressions.Extensions.GetMemberGetter(field.ColumnDescriptor.MemberInfo, param);
                            var tgtExpr    = mergeContext.TargetContext.ConvertToSql(builder.ConvertExpression(expression), 1, ConvertFlags.Field)[0].Sql;
                            var srcExpr    = mergeContext.SourceContext.ConvertToSql(builder.ConvertExpression(expression), 1, ConvertFlags.Field)[0].Sql;

                            operation.Items.Add(new SqlSetExpression(tgtExpr, srcExpr));
                        }
                        else if (field.IsIdentity)
                        {
                            var expr = builder.DataContext.CreateSqlProvider().GetIdentityExpression(sqlTable);

                            if (expr != null)
                            {
                                operation.Items.Add(new SqlSetExpression(field, expr));
                            }
                        }
                    }
                }

                if (!predicate.IsNullValue())
                {
                    var condition     = (LambdaExpression)predicate.Unwrap();
                    var conditionExpr = builder.ConvertExpression(condition.Body.Unwrap());

                    operation.Where = new SqlSearchCondition();

                    builder.BuildSearchCondition(
                        new ExpressionContext(null, new[] { mergeContext.SourceContext }, condition),
                        conditionExpr,
                        operation.Where.Conditions);
                }

                return(mergeContext);
            }