예제 #1
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence     = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
			var defaultValue = methodCall.Arguments.Count == 1 ? null : methodCall.Arguments[1].Unwrap();

			return new DefaultIfEmptyContext(sequence, defaultValue);
		}
예제 #2
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var selector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

            sequence.SetAlias(selector.Parameters[0].Name);

            var body = selector.Body.Unwrap();

            // .Select(p => p)
            //
            //if (body == selector.Parameters[0])
            //	return sequence;

            switch (body.NodeType)
            {
            case ExpressionType.Parameter: break;

            default:
                sequence = CheckSubQueryForSelect(sequence);
                break;
            }

            return(selector.Parameters.Count == 1 ? new SelectContext(selector, sequence) : new SelectContext2(selector, sequence));
        }
예제 #3
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence     = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
            var defaultValue = methodCall.Arguments.Count == 1 ? null : methodCall.Arguments[1].Unwrap();

            return(new DefaultIfEmptyContext(sequence, defaultValue));
        }
예제 #4
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence  = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
            var condition = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var result    = parser.ParseWhere(sequence, condition, true);

            result.SetAlias(condition.Parameters[0].Name);

            return(result);
        }
예제 #5
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence  = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
			var condition = (LambdaExpression)methodCall.Arguments[1].Unwrap();
			var result    = parser.ParseWhere(sequence, condition, true);

			result.SetAlias(condition.Parameters[0].Name);

			return result;
		}
예제 #6
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
			var sql      = sequence.SqlQuery;

			if (sql.Select.TakeValue != null || sql.Select.SkipValue != null)
				sequence = new SubQueryContext(sequence);

			sequence.SqlQuery.Select.IsDistinct = true;

			return sequence;
		}
예제 #7
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence        = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
			var sequenceExpr    = methodCall.Arguments[0];
			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(ExpressionParser.GroupSubQuery<,>))
					{
						sequence = new SubQueryContext(sequence);
					}
				}
			}

			var key      = new KeyContext(keySelector, sequence);
			var groupSql = parser.ParseExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);

			if (groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SqlQuery.Column)))
			{
				sequence = new SubQueryContext(sequence);
				key      = new KeyContext(keySelector, sequence);
				groupSql = parser.ParseExpressions(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 (elementSelector, sequence);
			var groupBy = new GroupByContext(sequenceExpr, groupingType, sequence, key, element);

			return groupBy;
		}
예제 #8
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
            var sql      = sequence.SqlQuery;

            if (sql.Select.TakeValue != null || sql.Select.SkipValue != null)
            {
                sequence = new SubQueryContext(sequence);
            }

            sequence.SqlQuery.Select.IsDistinct = true;

            return(sequence);
        }
예제 #9
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

            if (sequence.SqlQuery.Select.IsDistinct || sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null)
            {
                //sequence.ConvertToIndex(null, 0, ConvertFlags.All);
                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);
                }
            }

            if (methodCall.Arguments.Count == 2)
            {
                var lambda  = (LambdaExpression)methodCall.Arguments[1].Unwrap();
                var context = new AggregationContext(sequence, lambda, methodCall.Method.ReturnType);

                context.FieldIndex = context.SqlQuery.Select.Add(
                    new SqlFunction(
                        methodCall.Type,
                        methodCall.Method.Name,
                        parser.ParseExpression(context, context.Lambda.Body.Unwrap())));

                return(context);
            }
            else
            {
                var context = new AggregationContext(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);
            }
        }
예제 #10
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

            if (sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null)
            {
                sequence = new SubQueryContext(sequence);
            }

            var lambda = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var order  = new PathThroughContext(sequence, lambda);
            var body   = lambda.Body.Unwrap();
            var sql    = parser.ParseExpressions(order, body, ConvertFlags.Key);

            if (!methodCall.Method.Name.StartsWith("Then"))
            {
                sequence.SqlQuery.OrderBy.Items.Clear();
            }

            foreach (var expr in sql)
            {
                var e = expr.Sql;

                if (e is SqlQuery.SearchCondition)
                {
                    if (e.CanBeNull())
                    {
                        var notExpr = new SqlQuery.SearchCondition
                        {
                            Conditions = { new SqlQuery.Condition(true, new SqlQuery.Predicate.Expr(e, e.Precedence)) }
                        };

                        e = parser.Convert(sequence, new SqlFunction(e.SystemType, "CASE", e, new SqlValue(1), notExpr, new SqlValue(0), new SqlValue(null)));
                    }
                    else
                    {
                        e = parser.Convert(sequence, new SqlFunction(e.SystemType, "CASE", e, new SqlValue(1), new SqlValue(0)));
                    }
                }

                sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending"));
            }

            return(sequence);
        }
예제 #11
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

            if (methodCall.Arguments.Count == 2)
            {
                var condition = (LambdaExpression)methodCall.Arguments[1].Unwrap();

                sequence = parser.ParseWhere(sequence, condition, true);
                sequence.SetAlias(condition.Parameters[0].Name);
            }

            var take = 0;

            if (parser.SubQueryParsingCounter == 0 || parser.SqlProvider.IsSubQueryTakeSupported)
            {
                switch (methodCall.Method.Name)
                {
                case "First":
                case "FirstOrDefault":
                    take = 1;
                    break;

                case "Single":
                case "SingleOrDefault":
                    if (parser.SubQueryParsingCounter == 0)
                    {
                        take = 2;
                    }
                    break;
                }
            }

            if (take != 0)
            {
                parser.ParseTake(sequence, new SqlValue(take));
            }

            //sequence.BuildExpression(null, 0);

            return(new FirstSingleContext(sequence, methodCall.Method.Name));
        }
예제 #12
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

			if (sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null)
				sequence = new SubQueryContext(sequence);

			var lambda = (LambdaExpression)methodCall.Arguments[1].Unwrap();
			var order  = new PathThroughContext(sequence, lambda);
			var body   = lambda.Body.Unwrap();
			var sql    = parser.ParseExpressions(order, body, ConvertFlags.Key);

			if (!methodCall.Method.Name.StartsWith("Then"))
				sequence.SqlQuery.OrderBy.Items.Clear();

			foreach (var expr in sql)
			{
				var e = expr.Sql;

				if (e is SqlQuery.SearchCondition)
				{
					if (e.CanBeNull())
					{
						var notExpr = new SqlQuery.SearchCondition
						{
							Conditions = { new SqlQuery.Condition(true, new SqlQuery.Predicate.Expr(e, e.Precedence)) }
						};

						e = parser.Convert(sequence, new SqlFunction(e.SystemType, "CASE", e, new SqlValue(1), notExpr, new SqlValue(0), new SqlValue(null)));
					}
					else
						e = parser.Convert(sequence, new SqlFunction(e.SystemType, "CASE", e, new SqlValue(1), new SqlValue(0)));
				}

				sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending"));
			}

			return sequence;
		}
예제 #13
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

			var arg = methodCall.Arguments[1].Unwrap();

			if (arg.NodeType == ExpressionType.Lambda)
				arg = ((LambdaExpression)arg).Body.Unwrap();

			var expr = parser.ParseExpression(sequence, arg);

			if (methodCall.Method.Name == "Take")
			{
				ParseTake(parser, sequence, expr);
			}
			else
			{
				ParseSkip(parser, sequence, sequence.SqlQuery.Select.SkipValue, expr);
			}

			return sequence;
		}
예제 #14
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

            if (sequence.SqlQuery.Select.IsDistinct || sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null)
            {
                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);
                }
            }

            if (methodCall.Arguments.Count == 2)
            {
                var condition = (LambdaExpression)methodCall.Arguments[1].Unwrap();

                sequence = parser.ParseWhere(sequence, condition, true);
                sequence.SetAlias(condition.Parameters[0].Name);
            }

            var context = new CountConext(sequence, methodCall.Method.ReturnType);

            context.FieldIndex = context.SqlQuery.Select.Add(SqlFunction.CreateCount(methodCall.Method.ReturnType, context.SqlQuery), "cnt");

            return(context);
        }
예제 #15
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);

            var arg = methodCall.Arguments[1].Unwrap();

            if (arg.NodeType == ExpressionType.Lambda)
            {
                arg = ((LambdaExpression)arg).Body.Unwrap();
            }

            var expr = parser.ParseExpression(sequence, arg);

            if (methodCall.Method.Name == "Take")
            {
                ParseTake(parser, sequence, expr);
            }
            else
            {
                ParseSkip(parser, sequence, sequence.SqlQuery.Select.SkipValue, expr);
            }

            return(sequence);
        }
예제 #16
0
 protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
 {
     return(parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery));
 }
예제 #17
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			return parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
		}
예제 #18
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var isGroup      = methodCall.Method.Name == "GroupJoin";
			var outerContext = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
			var innerContext = parser.ParseSequence(parent, methodCall.Arguments[1], new SqlQuery());

			outerContext = new SubQueryContext(outerContext);
			innerContext = new SubQueryContext(innerContext);

			var join = innerContext.SqlQuery.InnerJoin();
			var sql  = new SqlQuery();

			sql.From.Table(outerContext.SqlQuery, join);

			var selector = (LambdaExpression)methodCall.Arguments[4].Unwrap();

			outerContext.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 outerKeyContext = new PathThroughContext(outerContext, outerKeyLambda);
			var innerKeyContext = new PathThroughContext(innerContext, innerKeyLambda);

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

					var predicate = parser.ParseObjectComparison(ExpressionType.Equal, outerKeyContext, arg1, innerKeyContext, arg2);

					if (predicate != null)
						join.JoinedTable.Condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
					else
						join
							.Expr(parser.ParseExpression(outerKeyContext, arg1)).Equal
							.Expr(parser.ParseExpression(innerKeyContext, arg2));
				}
			}
			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;

					var predicate = parser.ParseObjectComparison(ExpressionType.Equal, outerKeyContext, arg1, innerKeyContext, arg2);

					if (predicate != null)
						join.JoinedTable.Condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
					else
						join
							.Expr(parser.ParseExpression(outerKeyContext, arg1)).Equal
							.Expr(parser.ParseExpression(innerKeyContext, arg2));
				}
			}
			else
			{
				var predicate = parser.ParseObjectComparison(
					ExpressionType.Equal,
					outerKeyContext, outerKeySelector,
					innerKeyContext, innerKeySelector);

				if (predicate != null)
					join.JoinedTable.Condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
				else
					join
						.Expr(parser.ParseExpression(outerKeyContext, outerKeySelector)).Equal
						.Expr(parser.ParseExpression(innerKeyContext, innerKeySelector));
			}

			return isGroup ?
				new GroupJoinContext(selector, outerContext, innerContext, sql) :
				new      JoinContext(selector, outerContext, innerContext, sql);
		}
예제 #19
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var sequence           = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
            var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var resultSelector     = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            //if (collectionSelector.Parameters[0] == collectionSelector.Body.Unwrap())
            //{
            //	return resultSelector == null ? sequence : new SelectContext(resultSelector, sequence, sequence);
            //}

            var context    = new SelectManyContext(collectionSelector, sequence);
            var expr       = collectionSelector.Body.Unwrap();
            var crossApply = null != expr.Find(e => e == collectionSelector.Parameters[0]);

            /*
             * if (expr.NodeType == ExpressionType.Call)
             * {
             *      var call = (MethodCallExpression)collectionSelector.Body;
             *
             *      if (call.IsQueryable("DefaultIfEmpty"))
             *      {
             *              leftJoin = true;
             *              expr     = call.Arguments[0];
             *      }
             * }
             */

            parser.SubQueryParsingCounter++;
            var collection = parser.ParseSequence(context, expr, new SqlQuery());

            parser.SubQueryParsingCounter--;

            var leftJoin = collection is DefaultIfEmptyParser.DefaultIfEmptyContext;
            var sql      = collection.SqlQuery;

            if (!leftJoin && crossApply)
            {
                if (sql.GroupBy.IsEmpty &&
                    sql.Select.Columns.Count == 0 &&
                    !sql.Select.HasModifier &&
                    sql.Where.IsEmpty &&
                    !sql.HasUnion &&
                    sql.From.Tables.Count == 1)
                {
                    crossApply = false;
                }
            }

            if (!leftJoin && !crossApply)
            {
                sequence.SqlQuery.From.Table(sql);

                //sql.ParentSql = sequence.SqlQuery;

                var col = (IParseContext) new SubQueryContext(collection, sequence.SqlQuery, true);

                return(new SelectContext(resultSelector, sequence, col));
            }

            //if (crossApply)
            {
                if (sql.GroupBy.IsEmpty &&
                    sql.Select.Columns.Count == 0 &&
                    !sql.Select.HasModifier &&
                    //!sql.Where.IsEmpty &&
                    !sql.HasUnion && sql.From.Tables.Count == 1)
                {
                    var join = leftJoin ? SqlQuery.LeftJoin(sql) : SqlQuery.InnerJoin(sql);

                    join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions);

                    sql.Where.SearchCondition.Conditions.Clear();

                    if (collection is TableParser.TableContext)
                    {
                        var collectionParent = collection.Parent as TableParser.TableContext;

                        if (collectionParent != null)
                        {
                            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);
                        }
                    }
                    else
                    {
                        sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                        //collection.SqlQuery = sequence.SqlQuery;
                    }

                    //sql.ParentSql = sequence.SqlQuery;

                    var col = (IParseContext) new SubQueryContext(collection, sequence.SqlQuery, false);

                    return(new SelectContext(resultSelector, sequence, col));
                }
            }

            throw new LinqException("Sequence '{0}' cannot be converted to SQL.", expr);
        }
예제 #20
0
        protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
        {
            var isGroup      = methodCall.Method.Name == "GroupJoin";
            var outerContext = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
            var innerContext = parser.ParseSequence(parent, methodCall.Arguments[1], new SqlQuery());

            outerContext = new SubQueryContext(outerContext);
            innerContext = new SubQueryContext(innerContext);

            var join = innerContext.SqlQuery.InnerJoin();
            var sql  = new SqlQuery();

            sql.From.Table(outerContext.SqlQuery, join);

            var selector = (LambdaExpression)methodCall.Arguments[4].Unwrap();

            outerContext.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 outerKeyContext = new PathThroughContext(outerContext, outerKeyLambda);
            var innerKeyContext = new PathThroughContext(innerContext, innerKeyLambda);

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

                    var predicate = parser.ParseObjectComparison(ExpressionType.Equal, outerKeyContext, arg1, innerKeyContext, arg2);

                    if (predicate != null)
                    {
                        join.JoinedTable.Condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
                    }
                    else
                    {
                        join
                        .Expr(parser.ParseExpression(outerKeyContext, arg1)).Equal
                        .Expr(parser.ParseExpression(innerKeyContext, arg2));
                    }
                }
            }
            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;

                    var predicate = parser.ParseObjectComparison(ExpressionType.Equal, outerKeyContext, arg1, innerKeyContext, arg2);

                    if (predicate != null)
                    {
                        join.JoinedTable.Condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
                    }
                    else
                    {
                        join
                        .Expr(parser.ParseExpression(outerKeyContext, arg1)).Equal
                        .Expr(parser.ParseExpression(innerKeyContext, arg2));
                    }
                }
            }
            else
            {
                var predicate = parser.ParseObjectComparison(
                    ExpressionType.Equal,
                    outerKeyContext, outerKeySelector,
                    innerKeyContext, innerKeySelector);

                if (predicate != null)
                {
                    join.JoinedTable.Condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
                }
                else
                {
                    join
                    .Expr(parser.ParseExpression(outerKeyContext, outerKeySelector)).Equal
                    .Expr(parser.ParseExpression(innerKeyContext, innerKeySelector));
                }
            }

            return(isGroup ?
                   new GroupJoinContext(selector, outerContext, innerContext, sql) :
                   new      JoinContext(selector, outerContext, innerContext, sql));
        }
예제 #21
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence           = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
			var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
			var resultSelector     = (LambdaExpression)methodCall.Arguments[2].Unwrap();

			//if (collectionSelector.Parameters[0] == collectionSelector.Body.Unwrap())
			//{
			//	return resultSelector == null ? sequence : new SelectContext(resultSelector, sequence, sequence);
			//}

			var context    = new SelectManyContext(collectionSelector, sequence);
			var expr       = collectionSelector.Body.Unwrap();
			var crossApply = null != expr.Find(e => e == collectionSelector.Parameters[0]);

			/*
			if (expr.NodeType == ExpressionType.Call)
			{
				var call = (MethodCallExpression)collectionSelector.Body;

				if (call.IsQueryable("DefaultIfEmpty"))
				{
					leftJoin = true;
					expr     = call.Arguments[0];
				}
			}
			*/

			parser.SubQueryParsingCounter++;
			var collection = parser.ParseSequence(context, expr, new SqlQuery());
			parser.SubQueryParsingCounter--;

			var leftJoin = collection is DefaultIfEmptyParser.DefaultIfEmptyContext;
			var sql      = collection.SqlQuery;

			if (!leftJoin && crossApply)
			{
				if (sql.GroupBy.IsEmpty &&
					sql.Select.Columns.Count == 0 &&
					!sql.Select.HasModifier &&
					sql.Where.IsEmpty &&
					!sql.HasUnion &&
					sql.From.Tables.Count == 1)
				{
					crossApply = false;
				}
			}

			if (!leftJoin && !crossApply)
			{
				sequence.SqlQuery.From.Table(sql);

				//sql.ParentSql = sequence.SqlQuery;

				var col = (IParseContext)new SubQueryContext(collection, sequence.SqlQuery, true);

				return new SelectContext(resultSelector, sequence, col);
			}

			//if (crossApply)
			{
				if (sql.GroupBy.IsEmpty &&
					sql.Select.Columns.Count == 0 &&
					!sql.Select.HasModifier &&
					//!sql.Where.IsEmpty &&
					!sql.HasUnion && sql.From.Tables.Count == 1)
				{
					var join = leftJoin ? SqlQuery.LeftJoin(sql) : SqlQuery.InnerJoin(sql);

					join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions);

					sql.Where.SearchCondition.Conditions.Clear();

					if (collection is TableParser.TableContext)
					{
						var collectionParent = collection.Parent as TableParser.TableContext;

						if (collectionParent != null)
						{
							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);
						}
					}
					else
					{
						sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);
						//collection.SqlQuery = sequence.SqlQuery;
					}

					//sql.ParentSql = sequence.SqlQuery;

					var col = (IParseContext)new SubQueryContext(collection, sequence.SqlQuery, false);

					return new SelectContext(resultSelector, sequence, col);
				}
			}

			throw new LinqException("Sequence '{0}' cannot be converted to SQL.", expr);
		}