Beispiel #1
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence           = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var resultSelector     = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            if (!sequence.SelectQuery.GroupBy.IsEmpty)
            {
                sequence = new SubQueryContext(sequence);
            }

            var context = new SelectManyContext(buildInfo.Parent, collectionSelector, sequence);
            var expr    = collectionSelector.Body.Unwrap();

            var collectionInfo = new BuildInfo(context, expr, new SelectQuery());
            var collection     = builder.BuildSequence(collectionInfo);
            var leftJoin       = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext;
            var sql            = collection.SelectQuery;

            var sequenceTables = new HashSet <ISqlTableSource>(sequence.SelectQuery.From.Tables[0].GetTables());
            var newQuery       = null != new QueryVisitor().Find(sql, e => e == collectionInfo.SelectQuery);
            var crossApply     = null != new QueryVisitor().Find(sql, e =>
                                                                 e.ElementType == QueryElementType.TableSource && sequenceTables.Contains((ISqlTableSource)e) ||
                                                                 e.ElementType == QueryElementType.SqlField && sequenceTables.Contains(((SqlField)e).Table) ||
                                                                 e.ElementType == QueryElementType.Column && sequenceTables.Contains(((SelectQuery.Column)e).Parent));

            if (collection is JoinBuilder.GroupJoinSubQueryContext)
            {
                var groupJoin = ((JoinBuilder.GroupJoinSubQueryContext)collection).GroupJoin;

                groupJoin.SelectQuery.From.Tables[0].Joins[0].JoinType = SelectQuery.JoinType.Inner;
                groupJoin.SelectQuery.From.Tables[0].Joins[0].IsWeak   = false;
            }

            if (!newQuery)
            {
                if (collection.SelectQuery.Select.HasModifier)
                {
                    if (crossApply)
                    {
                        var foundJoin = context.SelectQuery.FindJoin(j => j.Table.Source == collection.SelectQuery);
                        if (foundJoin != null)
                        {
                            foundJoin.JoinType = leftJoin ? SelectQuery.JoinType.OuterApply : SelectQuery.JoinType.CrossApply;

                            collection.SelectQuery.Where.ConcatSearchCondition(foundJoin.Condition);

                            ((ISqlExpressionWalkable)collection.SelectQuery.Where).Walk(false, e =>
                            {
                                var column = e as SelectQuery.Column;
                                if (column != null)
                                {
                                    if (column.Parent == collection.SelectQuery)
                                    {
                                        return(column.UnderlyingColumn);
                                    }
                                }
                                return(e);
                            });

                            foundJoin.Condition.Conditions.Clear();
                        }
                    }
                }

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }

            if (!crossApply)
            {
                if (!leftJoin)
                {
                    context.Collection = new SubQueryContext(collection, sequence.SelectQuery, true);
                    return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
                }
                else
                {
                    var join = SelectQuery.OuterApply(sql);
                    sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                    context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);

                    return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
                }
            }

            if (collection is TableBuilder.TableContext)
            {
                //				if (collectionInfo.IsAssociationBuilt)
                //				{
                //					context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                //					return new SelectContext(buildInfo.Parent, resultSelector, sequence, context);
                //				}

                var table = (TableBuilder.TableContext)collection;

                var isApplyJoin = collection.SelectQuery.Select.HasModifier ||
                                  table.SqlTable.TableArguments != null && table.SqlTable.TableArguments.Length > 0;

                var join = isApplyJoin
                    ? (leftJoin ? SelectQuery.OuterApply(sql) : SelectQuery.CrossApply(sql))
                    : (leftJoin ? SelectQuery.LeftJoin(sql) : SelectQuery.InnerJoin(sql));

                join.JoinedTable.CanConvertApply = false;

                if (!isApplyJoin)
                {
                    join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions);
                    sql.Where.SearchCondition.Conditions.Clear();
                }

                var collectionParent = collection.Parent as TableBuilder.TableContext;

                // Association.
                //
                if (collectionParent != null && collectionInfo.IsAssociationBuilt)
                {
                    var ts = (SelectQuery.TableSource) new QueryVisitor().Find(sequence.SelectQuery.From, e =>
                    {
                        if (e.ElementType == QueryElementType.TableSource)
                        {
                            var t = (SelectQuery.TableSource)e;
                            return(t.Source == collectionParent.SqlTable);
                        }

                        return(false);
                    });

                    ts.Joins.Add(join.JoinedTable);
                }
                else
                {
                    //if (collectionInfo.IsAssociationBuilt)
                    //{
                    //	collectionInfo.AssosiationContext.ParentAssociationJoin.IsWeak = false;
                    //}
                    //else
                    {
                        sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                    }
                }

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
            else
            {
                var join = leftJoin ? SelectQuery.OuterApply(sql) : SelectQuery.CrossApply(sql);
                sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
        }
Beispiel #2
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

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

            switch (methodCall.Arguments.Count)
            {
            case 1:                      // int Update<T>(this IUpdateable<T> source)
                CheckAssociation(sequence);
                break;

            case 2:                      // int Update<T>(this IQueryable<T> source, Expression<Func<T,T>> setter)
            {
                CheckAssociation(sequence);

                BuildSetter(
                    builder,
                    buildInfo,
                    (LambdaExpression)methodCall.Arguments[1].Unwrap(),
                    sequence,
                    sequence.SelectQuery.Update.Items,
                    sequence);
                break;
            }

            case 3:
            {
                var expr = methodCall.Arguments[1].Unwrap();

                if (expr is LambdaExpression && ((LambdaExpression)expr).ReturnType == typeof(bool))
                {
                    CheckAssociation(sequence);

                    // int Update<T>(this IQueryable<T> source, Expression<Func<T,bool>> predicate, Expression<Func<T,T>> setter)
                    //
                    sequence = builder.BuildWhere(buildInfo.Parent, sequence, (LambdaExpression)methodCall.Arguments[1].Unwrap(), false);

                    BuildSetter(
                        builder,
                        buildInfo,
                        (LambdaExpression)methodCall.Arguments[2].Unwrap(),
                        sequence,
                        sequence.SelectQuery.Update.Items,
                        sequence);
                }
                else
                {
                    IBuildContext into;

                    if (expr is LambdaExpression)
                    {
                        // static int Update<TSource,TTarget>(this IQueryable<TSource> source, Expression<Func<TSource,TTarget>> target, Expression<Func<TSource,TTarget>> setter)
                        //
                        var body      = ((LambdaExpression)expr).Body;
                        int level     = body.GetLevel();
                        var tableInfo = sequence.IsExpression(body, level, RequestFor.Table);

                        if (tableInfo.Result == false)
                        {
                            throw new LinqException("Expression '{0}' mast be a table.");
                        }

                        into = tableInfo.Context;
                    }
                    else
                    {
                        // static int Update<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter)
                        //
                        into = builder.BuildSequence(new BuildInfo(buildInfo, expr, new SelectQuery()));
                    }

                    sequence.ConvertToIndex(null, 0, ConvertFlags.All);
                    new SelectQueryOptimizer(builder.DataContextInfo.SqlProviderFlags, sequence.SelectQuery)
                    .ResolveWeakJoins(new List <ISqlTableSource>());
                    sequence.SelectQuery.Select.Columns.Clear();

                    BuildSetter(
                        builder,
                        buildInfo,
                        (LambdaExpression)methodCall.Arguments[2].Unwrap(),
                        into,
                        sequence.SelectQuery.Update.Items,
                        sequence);

                    var sql = sequence.SelectQuery;

                    sql.Select.Columns.Clear();

                    foreach (var item in sql.Update.Items)
                    {
                        sql.Select.Columns.Add(new SelectQuery.Column(sql, item.Expression));
                    }

                    sql.Update.Table = ((TableBuilder.TableContext)into).SqlTable;
                }

                break;
            }
            }

            sequence.SelectQuery.QueryType = QueryType.Update;

            return(new UpdateContext(buildInfo.Parent, sequence));
        }
Beispiel #4
0
        public IBuildContext BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
        {
            var call = (MethodCallExpression)buildInfo.Expression;

            return(new Context(builder.BuildSequence(new BuildInfo(buildInfo, call.Arguments[0]))));
        }
 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])));
 }