Beispiel #1
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var deleteType = methodCall.Method.Name switch
            {
                nameof(LinqExtensions.DeleteWithOutput) => DeleteContext.DeleteType.DeleteOutput,
                nameof(LinqExtensions.DeleteWithOutputInto) => DeleteContext.DeleteType.DeleteOutputInto,
                _ => DeleteContext.DeleteType.Delete,
            };

            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            if (methodCall.Arguments.Count == 2 && deleteType == DeleteContext.DeleteType.Delete)
            {
                sequence = builder.BuildWhere(buildInfo.Parent, sequence, (LambdaExpression)methodCall.Arguments[1].Unwrap(), false);
            }

            var deleteStatement = new SqlDeleteStatement(sequence.SelectQuery);

            sequence.Statement = deleteStatement;

            // Check association.
            //

            if (sequence is SelectContext ctx && ctx.IsScalar)
            {
                var res = ctx.IsExpression(null, 0, RequestFor.Association);

                if (res.Result)
                {
                    var isTableResult = res.Context !.IsExpression(null, 0, RequestFor.Table);
                    if (!isTableResult.Result)
                    {
                        throw new LinqException("Can not retrieve Table context from association.");
                    }

                    var atc = (TableBuilder.TableContext)isTableResult.Context !;
                    deleteStatement.Table = atc.SqlTable;
                }
                else
                {
                    res = ctx.IsExpression(null, 0, RequestFor.Table);

                    if (res.Result && res.Context is TableBuilder.TableContext context)
                    {
                        var tc = context;

                        if (deleteStatement.SelectQuery.From.Tables.Count == 0 || deleteStatement.SelectQuery.From.Tables[0].Source != tc.SelectQuery)
                        {
                            deleteStatement.Table = tc.SqlTable;
                        }
                    }
                }
            }

            var indexedParameters
                = methodCall.Method.GetParameters().Select((p, i) => Tuple.Create(p, i)).ToDictionary(t => t.Item1.Name, t => t.Item2);

            Expression GetArgumentByName(string name)
            {
                return(methodCall.Arguments[indexedParameters[name]]);
            }

            LambdaExpression GetOutputExpression(Type outputType)
            {
                if (!indexedParameters.TryGetValue("outputExpression", out var index))
                {
                    var param = Expression.Parameter(outputType);
                    return(Expression.Lambda(param, param));
                }

                return((LambdaExpression)methodCall.Arguments[index].Unwrap());
            }

            IBuildContext?   outputContext    = null;
            LambdaExpression?outputExpression = null;

            if (deleteType != DeleteContext.DeleteType.Delete)
            {
                outputExpression = GetOutputExpression(methodCall.Method.GetGenericArguments().Last());

                deleteStatement.Output = new SqlOutputClause();

                var deletedTable = SqlTable.Deleted(methodCall.Method.GetGenericArguments()[0]);

                outputContext = new TableBuilder.TableContext(builder, new SelectQuery(), deletedTable);

                deleteStatement.Output.DeletedTable = deletedTable;

                if (deleteType == DeleteContext.DeleteType.DeleteOutputInto)
                {
                    var outputTable = GetArgumentByName("outputTable");
                    var destination = builder.BuildSequence(new BuildInfo(buildInfo, outputTable, new SelectQuery()));

                    UpdateBuilder.BuildSetter(
                        builder,
                        buildInfo,
                        outputExpression,
                        destination,
                        deleteStatement.Output.OutputItems,
                        outputContext);

                    deleteStatement.Output.OutputTable = ((TableBuilder.TableContext)destination).SqlTable;
                }
            }

            if (deleteType == DeleteContext.DeleteType.DeleteOutput)
            {
                return(new DeleteWithOutputContext(buildInfo.Parent, sequence, outputContext !, outputExpression !));
            }

            return(new DeleteContext(buildInfo.Parent, sequence));
        }
Beispiel #2
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var mergeContext = (MergeContext)builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            var kind = MergeKind.Merge;

            if (methodCall.IsSameGenericMethod(MergeWithOutputInto))
            {
                kind = MergeKind.MergeWithOutputInto;
            }
            else if (methodCall.IsSameGenericMethod(MergeWithOutput))
            {
                kind = MergeKind.MergeWithOutput;
            }

            if (kind != MergeKind.Merge)
            {
                var objectType = methodCall.Method.GetGenericArguments()[0];

                var actionField   = SqlField.FakeField(new DbDataType(typeof(string)), "$action", false);
                var insertedTable = SqlTable.Inserted(objectType);
                var deletedTable  = SqlTable.Deleted(objectType);

                mergeContext.Merge.Output = new SqlOutputClause()
                {
                    InsertedTable = insertedTable,
                    DeletedTable  = deletedTable,
                };

                var selectQuery = new SelectQuery();

                var actionFieldContext  = new SingleExpressionContext(null, builder, actionField, selectQuery);
                var deletedTableContext = new TableBuilder.TableContext(builder, selectQuery, deletedTable);
                var insertedTableConext = new TableBuilder.TableContext(builder, selectQuery, insertedTable);

                if (kind == MergeKind.MergeWithOutput)
                {
                    var outputExpression = (LambdaExpression)methodCall.Arguments[1].Unwrap();

                    var outputContext = new MergeOutputContext(
                        buildInfo.Parent,
                        outputExpression,
                        mergeContext,
                        actionFieldContext,
                        deletedTableContext,
                        insertedTableConext
                        );

                    return(outputContext);
                }
                else
                {
                    var outputExpression = (LambdaExpression)methodCall.Arguments[2].Unwrap();

                    var outputTable = methodCall.Arguments[1];
                    var destination = builder.BuildSequence(new BuildInfo(buildInfo, outputTable, new SelectQuery()));

                    UpdateBuilder.BuildSetterWithContext(
                        builder,
                        buildInfo,
                        outputExpression,
                        destination,
                        mergeContext.Merge.Output.OutputItems,
                        actionFieldContext,
                        deletedTableContext,
                        insertedTableConext
                        );

                    mergeContext.Merge.Output.OutputTable = ((TableBuilder.TableContext)destination).SqlTable;
                }
            }

            return(mergeContext);
        }