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)); } }
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)); }
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)); }
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]))); }