protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var query = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var except = query.SqlQuery; sequence = new SubQueryContext(sequence); var sql = sequence.SqlQuery; except.ParentSql = sql; if (methodCall.Method.Name == "Except") sql.Where.Not.Exists(except); else sql.Where.Exists(except); var keys1 = sequence.ConvertToSql(null, 0, ConvertFlags.Key); var keys2 = query. ConvertToSql(null, 0, ConvertFlags.Key); if (keys1.Length != keys2.Length) throw new InvalidOperationException(); for (var i = 0; i < keys1.Length; i++) { except.Where .Expr(keys1[i].Sql) .Equal .Expr(keys2[i].Sql); } return sequence; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null) sequence = new SubQueryContext(sequence); var lambda = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var sparent = sequence.Parent; var order = new ExpressionContext(buildInfo.Parent, sequence, lambda); var body = lambda.Body.Unwrap(); var sql = builder.ConvertExpressions(order, body, ConvertFlags.Key); builder.ReplaceParent(order, sparent); //if (!methodCall.Method.Name.StartsWith("Then")) // sequence.SqlQuery.OrderBy.Items.Clear(); foreach (var expr in sql) { var e = builder.ConvertSearchCondition(sequence, expr.Sql); sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending")); } return sequence; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); } var lambda = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var sparent = sequence.Parent; var order = new ExpressionContext(buildInfo.Parent, sequence, lambda); var body = lambda.Body.Unwrap(); var sql = builder.ConvertExpressions(order, body, ConvertFlags.Key); builder.ReplaceParent(order, sparent); if (!methodCall.Method.Name.StartsWith("Then")) { sequence.SqlQuery.OrderBy.Items.Clear(); } foreach (var expr in sql) { var e = builder.ConvertSearchCondition(sequence, expr.Sql); sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending")); } return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequenceExpr = methodCall.Arguments[0]; var sequence = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr)); var groupingType = methodCall.Type.GetGenericArguments()[0]; var keySelector = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap(); if (methodCall.Arguments[0].NodeType == ExpressionType.Call) { var call = (MethodCallExpression)methodCall.Arguments[0]; if (call.Method.Name == "Select") { var type = ((LambdaExpression)call.Arguments[1].Unwrap()).Body.Type; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>)) { sequence = new SubQueryContext(sequence); } } } var key = new KeyContext(buildInfo.Parent, keySelector, sequence); var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key); if (sequence.SqlQuery.Select.IsDistinct || sequence.SqlQuery.GroupBy.Items.Count > 0 || groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SqlQuery.Column))) { sequence = new SubQueryContext(sequence); key = new KeyContext(buildInfo.Parent, keySelector, sequence); groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key); } //sequence.SqlQuery.GroupBy.Items.Clear(); foreach (var sql in groupSql) { sequence.SqlQuery.GroupBy.Expr(sql.Sql); } new QueryVisitor().Visit(sequence.SqlQuery.From, e => { if (e.ElementType == QueryElementType.JoinedTable) { var jt = (SqlQuery.JoinedTable)e; if (jt.JoinType == SqlQuery.JoinType.Inner) { jt.IsWeak = false; } } }); var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/); var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element); return(groupBy); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var isSubQuery = sequence.SqlQuery.Select.IsDistinct; if (isSubQuery) { sequence = new SubQueryContext(sequence); } switch (methodCall.Arguments.Count) { case 1: // static int Insert<T> (this IValueInsertable<T> source) // static int Insert<TSource,TTarget>(this ISelectInsertable<TSource,TTarget> source) { foreach (var item in sequence.SqlQuery.Set.Items) { sequence.SqlQuery.Select.Expr(item.Expression); } break; } case 2: // static int Insert<T>(this Table<T> target, Expression<Func<T>> setter) { UpdateBuilder.BuildSetter(builder, buildInfo, (LambdaExpression)methodCall.Arguments[1].Unwrap(), sequence, sequence); sequence.SqlQuery.Set.Into = ((TableBuilder.TableContext)sequence).SqlTable; sequence.SqlQuery.From.Tables.Clear(); break; } case 3: // static int Insert<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter) { var into = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); UpdateBuilder.BuildSetter(builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), into, sequence); sequence.SqlQuery.Select.Columns.Clear(); foreach (var item in sequence.SqlQuery.Set.Items) { sequence.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence.SqlQuery, item.Expression)); } sequence.SqlQuery.Set.Into = ((TableBuilder.TableContext)into).SqlTable; break; } } sequence.SqlQuery.QueryType = QueryType.Insert; sequence.SqlQuery.Set.WithIdentity = methodCall.Method.Name == "InsertWithIdentity"; return(new InsertContext(buildInfo.Parent, sequence, sequence.SqlQuery.Set.WithIdentity)); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var returnType = methodCall.Method.ReturnType; var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SqlQuery != buildInfo.SqlQuery) { if (sequence is JoinBuilder.GroupJoinSubQueryContext) { var ctx = new CountContext(buildInfo.Parent, sequence, returnType) { SqlQuery = ((JoinBuilder.GroupJoinSubQueryContext)sequence).GetCounter(methodCall) }; ctx.Sql = ctx.SqlQuery; ctx.FieldIndex = ctx.SqlQuery.Select.Add(SqlFunction.CreateCount(returnType, ctx.SqlQuery), "cnt"); return(ctx); } if (sequence is GroupByBuilder.GroupByContext) { return(new CountContext(buildInfo.Parent, sequence, returnType) { Sql = SqlFunction.CreateCount(returnType, sequence.SqlQuery), FieldIndex = -1 }); } } if (sequence.SqlQuery.Select.IsDistinct || sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null || !sequence.SqlQuery.GroupBy.IsEmpty) { sequence.ConvertToIndex(null, 0, ConvertFlags.Key); sequence = new SubQueryContext(sequence); } if (sequence.SqlQuery.OrderBy.Items.Count > 0) { if (sequence.SqlQuery.Select.TakeValue == null && sequence.SqlQuery.Select.SkipValue == null) { sequence.SqlQuery.OrderBy.Items.Clear(); } else { sequence = new SubQueryContext(sequence); } } var context = new CountContext(buildInfo.Parent, sequence, returnType); context.Sql = context.SqlQuery; context.FieldIndex = context.SqlQuery.Select.Add(SqlFunction.CreateCount(returnType, context.SqlQuery), "cnt"); return(context); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence1 = new SubQueryContext(builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]))); var sequence2 = new SubQueryContext(builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()))); var union = new SqlQuery.Union(sequence2.SqlQuery, methodCall.Method.Name == "Concat"); sequence1.SqlQuery.Unions.Add(union); return(new UnionContext(sequence1, sequence2, methodCall)); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var sql = sequence.SqlQuery; if (sql.Select.TakeValue != null || sql.Select.SkipValue != null) sequence = new SubQueryContext(sequence); sequence.SqlQuery.Select.IsDistinct = true; return sequence; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var sql = sequence.SqlQuery; if (sql.Select.TakeValue != null || sql.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); } sequence.SqlQuery.Select.IsDistinct = true; return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence1 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var sequence2 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var union = new SqlQuery.Union(sequence2.SqlQuery, methodCall.Method.Name == "Concat"); var sq = sequence1 as SubQueryContext; if (sq == null || sq.Union != null || !sq.SqlQuery.IsSimple) sq = new SubQueryContext(sequence1); sq.SubQuery.SqlQuery.Unions.Add(union); sq.Union = sequence2; return sq; }
public UnionContext(SubQueryContext sequence1, SubQueryContext sequence2, MethodCallExpression methodCall) : base(sequence1) { _methodCall = methodCall; _isObject = sequence1.IsExpression(null, 0, RequestFor.Object).Result || sequence2.IsExpression(null, 0, RequestFor.Object).Result; if (_isObject) { var type = _methodCall.Method.GetGenericArguments()[0]; _unionParameter = Expression.Parameter(type, "t"); } Init(sequence1, sequence2); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SqlQuery.Select.IsDistinct || sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null || !sequence.SqlQuery.GroupBy.IsEmpty) { sequence = new SubQueryContext(sequence); } if (!sequence.SqlQuery.OrderBy.IsEmpty) { if (sequence.SqlQuery.Select.TakeValue == null && sequence.SqlQuery.Select.SkipValue == null) { sequence.SqlQuery.OrderBy.Items.Clear(); } else { sequence = new SubQueryContext(sequence); } } var context = new AggregationContext(buildInfo.Parent, sequence, methodCall); var sql = sequence.ConvertToSql(null, 0, ConvertFlags.Field).Select(_ => _.Sql).ToArray(); if (sql.Length == 1 && sql[0] is SqlQuery) { var query = (SqlQuery)sql[0]; if (query.Select.Columns.Count == 1) { var join = SqlQuery.OuterApply(query); context.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable); sql[0] = query.Select.Columns[0]; } } context.Sql = context.SqlQuery; context.FieldIndex = context.SqlQuery.Select.Add( new SqlFunction(methodCall.Type, methodCall.Method.Name, sql)); return(context); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence1 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var sequence2 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var union = new SqlQuery.Union(sequence2.SqlQuery, methodCall.Method.Name == "Concat"); var sq = sequence1 as SubQueryContext; if (sq == null || sq.Union != null || !sq.SqlQuery.IsSimple) { sq = new SubQueryContext(sequence1); } sq.SubQuery.SqlQuery.Unions.Add(union); sq.Union = sequence2; return(sq); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SqlQuery != buildInfo.SqlQuery) { throw new NotImplementedException(); } if (sequence.SqlQuery.Select.IsDistinct || sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null || !sequence.SqlQuery.GroupBy.IsEmpty) { sequence = new SubQueryContext(sequence); } if (sequence.SqlQuery.OrderBy.Items.Count > 0) { if (sequence.SqlQuery.Select.TakeValue == null && sequence.SqlQuery.Select.SkipValue == null) { sequence.SqlQuery.OrderBy.Items.Clear(); } else { sequence = new SubQueryContext(sequence); } } //var index = sequence.ConvertToIndex(null, 0, ConvertFlags.Field); var context = new AggregationContext(buildInfo.Parent, sequence, null, methodCall.Method.ReturnType); context.FieldIndex = context.SqlQuery.Select.Add( new SqlFunction( methodCall.Type, methodCall.Method.Name, sequence.ConvertToSql(null, 0, ConvertFlags.Field).Select(_ => _.Sql).ToArray())); return(context); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var source = methodCall.Arguments[0].Unwrap(); var into = methodCall.Arguments[1].Unwrap(); IBuildContext sequence; // static IValueInsertable<T> Into<T>(this IDataContext dataContext, Table<T> target) // if (source.NodeType == ExpressionType.Constant && ((ConstantExpression)source).Value == null) { sequence = builder.BuildSequence(new BuildInfo((IBuildContext)null, into, new SqlQuery())); if (sequence.SqlQuery.Select.IsDistinct) { sequence = new SubQueryContext(sequence); } sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable; sequence.SqlQuery.From.Tables.Clear(); } // static ISelectInsertable<TSource,TTarget> Into<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target) // else { sequence = builder.BuildSequence(new BuildInfo(buildInfo, source)); if (sequence.SqlQuery.Select.IsDistinct) { sequence = new SubQueryContext(sequence); } var tbl = builder.BuildSequence(new BuildInfo((IBuildContext)null, into, new SqlQuery())); sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)tbl).SqlTable; } sequence.SqlQuery.Select.Columns.Clear(); return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var query = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var except = query.SqlQuery; sequence = new SubQueryContext(sequence); var sql = sequence.SqlQuery; except.ParentSql = sql; if (methodCall.Method.Name == "Except") { sql.Where.Not.Exists(except); } else { sql.Where.Exists(except); } var keys1 = sequence.ConvertToSql(null, 0, ConvertFlags.Key); var keys2 = query.ConvertToSql(null, 0, ConvertFlags.Key); if (keys1.Length != keys2.Length) { throw new InvalidOperationException(); } for (var i = 0; i < keys1.Length; i++) { except.Where .Expr(keys1[i].Sql) .Equal .Expr(keys2[i].Sql); } return(sequence); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var isSubQuery = sequence.SqlQuery.Select.IsDistinct; if (isSubQuery) { sequence = new SubQueryContext(sequence); } switch (methodCall.Arguments.Count) { case 1: // static int Insert<T> (this IValueInsertable<T> source) // static int Insert<TSource,TTarget>(this ISelectInsertable<TSource,TTarget> source) { foreach (var item in sequence.SqlQuery.Insert.Items) { sequence.SqlQuery.Select.Expr(item.Expression); } break; } case 2: // static int Insert<T>(this Table<T> target, Expression<Func<T>> setter) { UpdateBuilder.BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[1].Unwrap(), sequence, sequence.SqlQuery.Insert.Items, sequence); sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable; sequence.SqlQuery.From.Tables.Clear(); break; } case 3: // static int Insert<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter) { var into = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); UpdateBuilder.BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), into, sequence.SqlQuery.Insert.Items, sequence); sequence.SqlQuery.Select.Columns.Clear(); foreach (var item in sequence.SqlQuery.Insert.Items) { sequence.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence.SqlQuery, item.Expression)); } sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)into).SqlTable; break; } } var insert = sequence.SqlQuery.Insert; var q = insert.Into.Fields.Values.Cast <ISqlExpression>().Except(insert.Items.Select(e => e.Column)) .OfType <SqlField>() .Where(f => f.IsIdentity); foreach (var field in q) { var expr = builder.SqlProvider.GetIdentityExpression(insert.Into, field, false); if (expr != null) { insert.Items.Insert(0, new SqlQuery.SetExpression(field, expr)); if (methodCall.Arguments.Count == 3) { sequence.SqlQuery.Select.Columns.Insert(0, new SqlQuery.Column(sequence.SqlQuery, insert.Items[0].Expression)); } } } sequence.SqlQuery.QueryType = QueryType.Insert; sequence.SqlQuery.Insert.WithIdentity = methodCall.Method.Name == "InsertWithIdentity"; sequence.SqlQuery.Insert.WithOutput = methodCall.Method.Name == "InsertWithOutput"; return(new InsertContext(buildInfo.Parent, sequence, sequence.SqlQuery.Insert.WithIdentity || sequence.SqlQuery.Insert.WithOutput)); }
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.SqlQuery.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 SqlQuery()); var collection = builder.BuildSequence(collectionInfo); var leftJoin = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext; var sql = collection.SqlQuery; var sequenceTable = sequence.SqlQuery.From.Tables[0].Source; var newQuery = null != new QueryVisitor().Find(sql, e => e == collectionInfo.SqlQuery); var crossApply = null != new QueryVisitor().Find(sql, e => e == sequenceTable || e.ElementType == QueryElementType.SqlField && sequenceTable == ((SqlField)e).Table || e.ElementType == QueryElementType.Column && sequenceTable == ((SqlQuery.Column)e).Parent); if (collection is JoinBuilder.GroupJoinSubQueryContext) { var groupJoin = ((JoinBuilder.GroupJoinSubQueryContext)collection).GroupJoin; groupJoin.SqlQuery.From.Tables[0].Joins[0].JoinType = SqlQuery.JoinType.Inner; groupJoin.SqlQuery.From.Tables[0].Joins[0].IsWeak = false; } if (!newQuery) { context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } if (!crossApply) { if (!leftJoin) { context.Collection = new SubQueryContext(collection, sequence.SqlQuery, true); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } else { var join = SqlQuery.OuterApply(sql); sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable); context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } } if (collection is TableBuilder.TableContext) { var table = (TableBuilder.TableContext)collection; var join = table.SqlTable.TableArguments != null && table.SqlTable.TableArguments.Length > 0 ? leftJoin ? SqlQuery.OuterApply(sql) : SqlQuery.CrossApply(sql) : leftJoin?SqlQuery.LeftJoin(sql) : SqlQuery.InnerJoin(sql); 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 = (SqlQuery.TableSource) new QueryVisitor().Find(sequence.SqlQuery.From, e => { if (e.ElementType == QueryElementType.TableSource) { var t = (SqlQuery.TableSource)e; return(t.Source == collectionParent.SqlTable); } return(false); }); ts.Joins.Add(join.JoinedTable); } else { sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable); } context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } else { var join = leftJoin ? SqlQuery.OuterApply(sql) : SqlQuery.CrossApply(sql); sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable); context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } }
void Init(SubQueryContext sequence1, SubQueryContext sequence2) { var info1 = sequence1.ConvertToIndex(null, 0, ConvertFlags.All).ToList(); var info2 = sequence2.ConvertToIndex(null, 0, ConvertFlags.All).ToList(); if (!_isObject) { return; } var members = new List <UnionMember>(); foreach (var info in info1) { if (info.Members.Count == 0) { throw new InvalidOperationException(); } var member = new Member { SequenceInfo = info, MemberExpression = Expression.MakeMemberAccess(_unionParameter, info.Members[0]) }; //if (sequence1.IsExpression(member.MemberExpression, 1, RequestFor.Object).Result) // throw new LinqException("Types in {0} are constructed incompatibly.", _methodCall.Method.Name); members.Add(new UnionMember { Member = member, Info1 = info }); } foreach (var info in info2) { if (info.Members.Count == 0) { throw new InvalidOperationException(); } var em = members.FirstOrDefault(m => m.Member.SequenceInfo != null && m.Member.SequenceInfo.CompareMembers(info)); if (em == null) { var member = new Member { MemberExpression = Expression.MakeMemberAccess(_unionParameter, info.Members[0]) }; if (sequence2.IsExpression(member.MemberExpression, 1, RequestFor.Object).Result) { throw new LinqException("Types in {0} are constructed incompatibly.", _methodCall.Method.Name); } members.Add(new UnionMember { Member = member, Info2 = info }); } else { em.Info2 = info; } } sequence1.SqlQuery.Select.Columns.Clear(); sequence2.SqlQuery.Select.Columns.Clear(); for (var i = 0; i < members.Count; i++) { var member = members[i]; if (member.Info1 == null) { member.Info1 = new SqlInfo(member.Info2.Members) { Sql = new SqlValue(null), Query = sequence1.SqlQuery, }; member.Member.SequenceInfo = member.Info1; } if (member.Info2 == null) { member.Info2 = new SqlInfo(member.Info1.Members) { Sql = new SqlValue(null), Query = sequence2.SqlQuery, }; } sequence1.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence1.SqlQuery, member.Info1.Sql)); sequence2.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence2.SqlQuery, member.Info2.Sql)); member.Member.SequenceInfo.Index = i; //member.Info1.Index = i; //member.Info2.Index = i; _members[member.Member.MemberExpression.Member] = member.Member; } foreach (var key in sequence1.ColumnIndexes.Keys.ToList()) { sequence1.ColumnIndexes[key] = sequence1.SqlQuery.Select.Add(key); } foreach (var key in sequence2.ColumnIndexes.Keys.ToList()) { sequence2.ColumnIndexes[key] = sequence2.SqlQuery.Select.Add(key); } /* * if (_isObject) * { * foreach (var info in info1) * { * if (info.Member == null) * throw new InvalidOperationException(); * * CheckAndAddMember(sequence1, sequence2, info); * } * * info2 = sequence2.ConvertToIndex(null, 0, ConvertFlags.All).OrderBy(_ => _.Index).ToList(); * * if (info1.Count != info2.Count) * { * for (var i = 0; i < info2.Count; i++) * { * if (i < info1.Count) * { * if (info1[i].Index != info2[i].Index) * throw new InvalidOperationException(); * } * else * { * CheckAndAddMember(sequence2, sequence1, info2[i]); * } * } * } * } * else * sequence2.ConvertToIndex(null, 0, ConvertFlags.All).OrderBy(_ => _.Index).ToList(); */ }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var isGroup = methodCall.Method.Name == "GroupJoin"; var outerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0], buildInfo.SqlQuery)); var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var countContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var context = new SubQueryContext(outerContext); innerContext = isGroup ? new GroupJoinSubQueryContext(innerContext, methodCall) : new SubQueryContext(innerContext); countContext = new SubQueryContext(countContext); var join = isGroup ? innerContext.SqlQuery.WeakLeftJoin() : innerContext.SqlQuery.InnerJoin(); var sql = context.SqlQuery; sql.From.Tables[0].Joins.Add(join.JoinedTable); var selector = (LambdaExpression)methodCall.Arguments[4].Unwrap(); context.SetAlias(selector.Parameters[0].Name); innerContext.SetAlias(selector.Parameters[1].Name); var outerKeyLambda = ((LambdaExpression)methodCall.Arguments[2].Unwrap()); var innerKeyLambda = ((LambdaExpression)methodCall.Arguments[3].Unwrap()); var outerKeySelector = outerKeyLambda.Body.Unwrap(); var innerKeySelector = innerKeyLambda.Body.Unwrap(); var outerParent = context.Parent; var innerParent = innerContext.Parent; var countParent = countContext.Parent; var outerKeyContext = new ExpressionContext(buildInfo.Parent, context, outerKeyLambda); var innerKeyContext = new InnerKeyContext(buildInfo.Parent, innerContext, innerKeyLambda); var countKeyContext = new ExpressionContext(buildInfo.Parent, countContext, innerKeyLambda); // Process counter. // var counterSql = ((SubQueryContext)countContext).SqlQuery; // Make join and where for the counter. // if (outerKeySelector.NodeType == ExpressionType.New) { var new1 = (NewExpression)outerKeySelector; var new2 = (NewExpression)innerKeySelector; for (var i = 0; i < new1.Arguments.Count; i++) { var arg1 = new1.Arguments[i]; var arg2 = new2.Arguments[i]; BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql); } } else if (outerKeySelector.NodeType == ExpressionType.MemberInit) { var mi1 = (MemberInitExpression)outerKeySelector; var mi2 = (MemberInitExpression)innerKeySelector; for (var i = 0; i < mi1.Bindings.Count; i++) { if (mi1.Bindings[i].Member != mi2.Bindings[i].Member) { throw new LinqException(string.Format("List of member inits does not match for entity type '{0}'.", outerKeySelector.Type)); } var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression; var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression; BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql); } } else { BuildJoin(builder, join, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector, countKeyContext, counterSql); } builder.ReplaceParent(outerKeyContext, outerParent); builder.ReplaceParent(innerKeyContext, innerParent); builder.ReplaceParent(countKeyContext, countParent); if (isGroup) { counterSql.ParentSql = sql; counterSql.Select.Columns.Clear(); var inner = (GroupJoinSubQueryContext)innerContext; inner.Join = join.JoinedTable; inner.CounterSql = counterSql; return(new GroupJoinContext( buildInfo.Parent, selector, context, inner, methodCall.Arguments[1], outerKeyLambda, innerKeyLambda)); } return(new JoinContext(buildInfo.Parent, selector, context, innerContext) #if DEBUG { MethodCall = methodCall } #endif ); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var isGroup = methodCall.Method.Name == "GroupJoin"; var outerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0], buildInfo.SqlQuery)); var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var countContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var context = new SubQueryContext(outerContext); innerContext = isGroup ? new GroupJoinSubQueryContext(innerContext, methodCall) : new SubQueryContext(innerContext); countContext = new SubQueryContext(countContext); var join = innerContext.SqlQuery.InnerJoin(); var sql = context.SqlQuery; sql.From.Tables[0].Joins.Add(join.JoinedTable); var selector = (LambdaExpression)methodCall.Arguments[4].Unwrap(); context.SetAlias(selector.Parameters[0].Name); innerContext.SetAlias(selector.Parameters[1].Name); var outerKeyLambda = ((LambdaExpression)methodCall.Arguments[2].Unwrap()); var innerKeyLambda = ((LambdaExpression)methodCall.Arguments[3].Unwrap()); var outerKeySelector = outerKeyLambda.Body.Unwrap(); var innerKeySelector = innerKeyLambda.Body.Unwrap(); var outerParent = context. Parent; var innerParent = innerContext.Parent; var countParent = countContext.Parent; var outerKeyContext = new ExpressionContext(buildInfo.Parent, context, outerKeyLambda); var innerKeyContext = new ExpressionContext(buildInfo.Parent, innerContext, innerKeyLambda); var countKeyContext = new ExpressionContext(buildInfo.Parent, countContext, innerKeyLambda); // Process counter. // var counterSql = ((SubQueryContext)countContext).SqlQuery; // Make join and where for the counter. // if (outerKeySelector.NodeType == ExpressionType.New) { var new1 = (NewExpression)outerKeySelector; var new2 = (NewExpression)innerKeySelector; for (var i = 0; i < new1.Arguments.Count; i++) { var arg1 = new1.Arguments[i]; var arg2 = new2.Arguments[i]; BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql); } } else if (outerKeySelector.NodeType == ExpressionType.MemberInit) { var mi1 = (MemberInitExpression)outerKeySelector; var mi2 = (MemberInitExpression)innerKeySelector; for (var i = 0; i < mi1.Bindings.Count; i++) { if (mi1.Bindings[i].Member != mi2.Bindings[i].Member) throw new LinqException(string.Format("List of member inits does not match for entity type '{0}'.", outerKeySelector.Type)); var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression; var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression; BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql); } } else { BuildJoin(builder, join, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector, countKeyContext, counterSql); } context. Parent = outerParent; innerContext.Parent = innerParent; countContext.Parent = countParent; if (isGroup) { counterSql.ParentSql = sql; counterSql.Select.Columns.Clear(); var inner = (GroupJoinSubQueryContext)innerContext; inner.Join = join.JoinedTable; inner.CounterSql = counterSql; return new GroupJoinContext(buildInfo.Parent, selector, context, inner); } return new JoinContext(buildInfo.Parent, selector, context, innerContext); }