コード例 #1
0
            public AssociatedTableContext(
                [JetBrains.Annotations.NotNull] ExpressionBuilder builder,
                [JetBrains.Annotations.NotNull] TableContext parent,
                [JetBrains.Annotations.NotNull] AssociationDescriptor association
                )
                : base(builder, parent.SelectQuery)
            {
                if (builder == null)
                {
                    throw new ArgumentNullException(nameof(builder));
                }
                if (parent == null)
                {
                    throw new ArgumentNullException(nameof(parent));
                }
                if (association == null)
                {
                    throw new ArgumentNullException(nameof(association));
                }

                var type = association.MemberInfo.GetMemberType();
                var left = association.CanBeNull;

                if (typeof(IEnumerable).IsSameOrParentOf(type))
                {
                    var eTypes = type.GetGenericArguments(typeof(IEnumerable <>));
                    type   = eTypes != null && eTypes.Length > 0 ? eTypes[0] : type.GetListItemType();
                    IsList = true;
                }

                OriginalType       = type;
                ObjectType         = GetObjectType();
                EntityDescriptor   = Builder.MappingSchema.GetEntityDescriptor(ObjectType);
                InheritanceMapping = EntityDescriptor.InheritanceMapping;
                SqlTable           = new SqlTable(builder.MappingSchema, ObjectType);

                Association       = association;
                ParentAssociation = parent;

                SqlJoinedTable join;

                var queryMethod = Association.GetQueryMethod(parent.ObjectType, ObjectType);

                if (queryMethod != null)
                {
                    var selectManyMethod = GetAssociationQueryExpression(Expression.Constant(builder.DataContext),
                                                                         queryMethod.Parameters[0], parent.ObjectType, parent.Expression, queryMethod);

                    var ownerTableSource = SelectQuery.From.Tables[0];

                    var buildInfo = new BuildInfo(this, selectManyMethod, new SelectQuery())
                    {
                        IsAssociationBuilt = true
                    };
                    _innerContext = builder.BuildSequence(buildInfo);

                    if (Association.CanBeNull)
                    {
                        _innerContext = new DefaultIfEmptyBuilder.DefaultIfEmptyContext(buildInfo.Parent, _innerContext, null);
                    }

                    var associationQuery = _innerContext.SelectQuery;

                    if (associationQuery.Select.From.Tables.Count < 1)
                    {
                        throw new LinqToDBException("Invalid association query. It is not possible to inline query.");
                    }

                    var foundIndex = associationQuery.Select.From.Tables.FindIndex(t =>
                                                                                   t.Source is SqlTable sqlTable && QueryHelper.IsEqualTables(sqlTable, parent.SqlTable));

                    // try to search table by object type
                    // TODO: review maybe there are another ways to do that
                    if (foundIndex < 0)
                    {
                        foundIndex = associationQuery.Select.From.Tables.FindIndex(t =>
                                                                                   t.Source is SqlTable sqlTable && sqlTable.ObjectType == parent.SqlTable.ObjectType);
                    }

                    if (foundIndex < 0)
                    {
                        throw new LinqToDBException("Invalid association query. It is not possible to inline query. Can not find owner table.");
                    }

                    var sourceToReplace = associationQuery.Select.From.Tables[foundIndex];

                    if (left)
                    {
                        foreach (var joinedTable in sourceToReplace.Joins)
                        {
                            if (joinedTable.JoinType == JoinType.Inner)
                            {
                                joinedTable.JoinType = JoinType.Left;
                            }
                            else if (joinedTable.JoinType == JoinType.CrossApply)
                            {
                                joinedTable.JoinType = JoinType.OuterApply;
                            }

                            joinedTable.IsWeak = true;
                        }
                    }

                    ownerTableSource.Joins.AddRange(sourceToReplace.Joins);

                    // prepare fields mapping to replace fields that will be generated by association query
                    _replaceMap =
                        ((SqlTable)sourceToReplace.Source).Fields.Values.ToDictionary(f => (ISqlExpression)f,
                                                                                      f => parent.SqlTable.Fields[f.Name]);

                    ownerTableSource.Walk(new WalkOptions(), e =>
                    {
                        if (_replaceMap.TryGetValue(e, out var newField))
                        {
                            return(newField);
                        }
                        return(e);
                    });

                    ParentAssociationJoin = sourceToReplace.Joins.FirstOrDefault();
                    join = ParentAssociationJoin;

                    // add rest of tables
                    SelectQuery.From.Tables.AddRange(associationQuery.Select.From.Tables.Where(t => t != sourceToReplace));

                    //TODO: Change AssociatedTableContext base class
                    //SqlTable = null;
                }
                else
                {
                    var psrc = parent.SelectQuery.From[parent.SqlTable];
                    join = left ? SqlTable.WeakLeftJoin().JoinedTable : SqlTable.WeakInnerJoin().JoinedTable;

                    ParentAssociationJoin = join;

                    psrc.Joins.Add(join);

                    for (var i = 0; i < association.ThisKey.Length; i++)
                    {
                        if (!parent.SqlTable.Fields.TryGetValue(association.ThisKey[i], out var field1))
                        {
                            throw new LinqException("Association key '{0}' not found for type '{1}.", association.ThisKey[i], parent.ObjectType);
                        }

                        if (!SqlTable.Fields.TryGetValue(association.OtherKey[i], out var field2))
                        {
                            throw new LinqException("Association key '{0}' not found for type '{1}.", association.OtherKey[i], ObjectType);
                        }

                        //					join.Field(field1).Equal.Field(field2);

                        ISqlPredicate predicate = new SqlPredicate.ExprExpr(
                            field1, SqlPredicate.Operator.Equal, field2);

                        predicate = builder.Convert(parent, predicate);

                        join.Condition.Conditions.Add(new SqlCondition(false, predicate));
                    }

                    if (ObjectType != OriginalType)
                    {
                        var predicate = Builder.MakeIsPredicate(this, OriginalType);

                        if (predicate.GetType() != typeof(SqlPredicate.Expr))
                        {
                            join.Condition.Conditions.Add(new SqlCondition(false, predicate));
                        }
                    }

                    RegularConditionCount = join.Condition.Conditions.Count;
                    ExpressionPredicate   = Association.GetPredicate(parent.ObjectType, ObjectType);

                    if (ExpressionPredicate != null)
                    {
                        ExpressionPredicate = (LambdaExpression)Builder.ConvertExpressionTree(ExpressionPredicate);

                        var expr = Builder.ConvertExpression(ExpressionPredicate.Body.Unwrap());

                        Builder.BuildSearchCondition(
                            new ExpressionContext(parent.Parent, new IBuildContext[] { parent, this }, ExpressionPredicate),
                            expr,
                            join.Condition.Conditions,
                            false);
                    }
                }

                if (!association.AliasName.IsNullOrEmpty() && join != null)
                {
                    join.Table.Alias = association.AliasName;
                }
                else
                {
                    if (!Common.Configuration.Sql.AssociationAlias.IsNullOrEmpty() && join != null)
                    {
                        join.Table.Alias = string.Format(Common.Configuration.Sql.AssociationAlias,
                                                         association.MemberInfo.Name);
                    }
                }

                Init(false);
            }
コード例 #2
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var take     = 0;

            if (!buildInfo.IsSubQuery || builder.DataContextInfo.SqlProviderFlags.IsSubQueryTakeSupported)
            {
                switch (methodCall.Method.Name)
                {
                case "First":
                case "FirstOrDefault":
                    take = 1;
                    break;

                case "Single":
                case "SingleOrDefault":
                    if (!buildInfo.IsSubQuery)
                    {
                        var takeValue = buildInfo.SelectQuery.Select.TakeValue as SqlValue;
                        if (takeValue != null && (int)takeValue.Value >= 2)
                        {
                            take = 2;
                        }
                    }
                    break;
                }
            }

            if (take != 0)
            {
                builder.BuildTake(sequence, new SqlValue(take), null);
            }

            return(new FirstSingleContext(buildInfo.Parent, sequence, methodCall));
        }
コード例 #3
0
ファイル: ContainsBuilder.cs プロジェクト: yallie/linq2db
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return
         (methodCall.IsQueryable(MethodNames) && methodCall.Arguments.Count == 2 ||
          methodCall.IsAsyncExtension(MethodNamesAsync) && methodCall.Arguments.Count == 3);
 }
コード例 #4
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            var wrapped = false;

            if (sequence.SelectQuery.Select.HasModifier)
            {
                sequence = new SubQueryContext(sequence);
                wrapped  = true;
            }

            var isContinuousOrder = !sequence.SelectQuery.OrderBy.IsEmpty && methodCall.Method.Name.StartsWith("Then");
            var lambda            = (LambdaExpression)methodCall.Arguments[1].Unwrap();

            SqlInfo[] sql;

            while (true)
            {
                var sparent = sequence.Parent;
                var order   = new ExpressionContext(buildInfo.Parent, sequence, lambda);
                var body    = lambda.Body.Unwrap();
                sql = builder.ConvertExpressions(order, body, ConvertFlags.Key, null);

                builder.ReplaceParent(order, sparent);

                // Do not create subquery for ThenByExtensions
                if (wrapped || isContinuousOrder)
                {
                    break;
                }

                // handle situation when order by uses complex field

                var isComplex = false;

                foreach (var sqlInfo in sql)
                {
                    // immutable expressions will be removed later
                    //
                    var isImmutable = QueryHelper.IsConstant(sqlInfo.Sql);
                    if (isImmutable)
                    {
                        continue;
                    }

                    // possible we have to extend this list
                    //
                    isComplex = null != sqlInfo.Sql.Find(QueryElementType.SqlQuery);
                    if (isComplex)
                    {
                        break;
                    }
                }

                if (!isComplex)
                {
                    break;
                }

                sequence = new SubQueryContext(sequence);
                wrapped  = true;
            }


            if (!isContinuousOrder && !Configuration.Linq.DoNotClearOrderBys)
            {
                sequence.SelectQuery.OrderBy.Items.Clear();
            }

            foreach (var expr in sql)
            {
                // we do not need sorting by immutable values, like "Some", Func("Some"), "Some1" + "Some2". It does nothing for ordering
                //
                if (QueryHelper.IsConstant(expr.Sql))
                {
                    continue;
                }

                sequence.SelectQuery.OrderBy.Expr(expr.Sql, methodCall.Method.Name.EndsWith("Descending"));
            }

            return(sequence);
        }
コード例 #5
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])
            {
                CreateSubQuery = true
            });

            if (sequence.SelectQuery.Select.IsDistinct ||
                sequence.SelectQuery.Select.TakeValue != null ||
                sequence.SelectQuery.Select.SkipValue != null ||
                !sequence.SelectQuery.GroupBy.IsEmpty)
            {
                sequence = new SubQueryContext(sequence);
            }

            if (sequence.SelectQuery.OrderBy.Items.Count > 0)
            {
                if (sequence.SelectQuery.Select.TakeValue == null && sequence.SelectQuery.Select.SkipValue == null)
                {
                    sequence.SelectQuery.OrderBy.Items.Clear();
                }
                else
                {
                    sequence = new SubQueryContext(sequence);
                }
            }

            var context = new AggregationContext(buildInfo.Parent, sequence, methodCall);

            var methodName = methodCall.Method.Name.Replace("Async", "");

            var sql = sequence.ConvertToSql(null, 0, ConvertFlags.Field).Select(_ => _.Sql).ToArray();

            if (sql.Length == 1 && sql[0] is SelectQuery query)
            {
                if (query.Select.Columns.Count == 1)
                {
                    var join = query.OuterApply();
                    context.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                    sql[0] = query.Select.Columns[0];
                }
            }

            ISqlExpression sqlExpression = new SqlFunction(methodCall.Type, methodName, true, sql);

            if (sqlExpression == null)
            {
                throw new LinqToDBException("Invalid Aggregate function implementation");
            }

            context.Sql        = context.SelectQuery;
            context.FieldIndex = context.SelectQuery.Select.Add(sqlExpression, methodName);

            return(context);
        }
コード例 #6
0
ファイル: SelectContext.cs プロジェクト: ijsgaus/linq2db
		public virtual IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo)
		{
			if (expression == null)
				return this;

			if (IsScalar)
			{
				return ProcessScalar(
					expression,
					level,
					(ctx, ex, l) => ctx.GetContext(ex, l, buildInfo),
					() => { throw new NotImplementedException(); });
			}
			else
			{
				var levelExpression = expression.GetLevelExpression(Builder.MappingSchema, level);

				switch (levelExpression.NodeType)
				{
					case ExpressionType.MemberAccess :
						{
							if (levelExpression == expression && Sequence.Length == 1 && !(Sequence[0] is GroupByBuilder.GroupByContext))
							{
								var memberExpression = GetMemberExpression(
									((MemberExpression)levelExpression).Member,
									levelExpression == expression,
									levelExpression.Type,
									expression);

								return GetContext(memberExpression, 0, new BuildInfo(this, memberExpression, buildInfo.SelectQuery));
							}

							var context = ProcessMemberAccess(
								expression,
								(MemberExpression)levelExpression,
								level,
								(n,ctx,ex,l,_) => n == 0 ?
									null :
									ctx.GetContext(ex, l, buildInfo));

							if (context == null)
								throw new NotImplementedException();

							return context;
						}

					case ExpressionType.Parameter    :
						{
							var sequence  = GetSequence(expression, level);
							var parameter = Lambda.Parameters[Sequence.Length == 0 ? 0 : Array.IndexOf(Sequence, sequence)];

							if (ReferenceEquals(levelExpression, expression))
							{
								if (ReferenceEquals(levelExpression, parameter))
									return sequence.GetContext(null, 0, buildInfo);
							}
							else if (level == 0)
								return sequence.GetContext(expression, 1, buildInfo);

							break;
						}
				}

				if (level == 0)
				{
					var sequence = GetSequence(expression, level);
					return sequence.GetContext(expression, level + 1, buildInfo);
				}
			}

			throw new NotImplementedException();
		}
コード例 #7
0
        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 SelectQuery())));
            var union     = new SqlUnion(sequence2.SelectQuery, methodCall.Method.Name == "Concat");

            sequence1.SelectQuery.Unions.Add(union);

            return(new UnionContext(sequence1, sequence2, methodCall));
        }
コード例 #8
0
 public SequenceConvertInfo?Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression?param)
 {
     return(Convert(builder, (MethodCallExpression)buildInfo.Expression, buildInfo, param));
 }
コード例 #9
0
 public virtual bool IsSequence(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return(builder.IsSequence(new BuildInfo(buildInfo, ((MethodCallExpression)buildInfo.Expression).Arguments[0])));
 }
コード例 #10
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            if (sequence is TableBuilder.TableContext table &&
                table.InheritanceMapping.Count > 0)
            {
                var objectType = methodCall.Type.GetGenericArguments()[0];

                if (table.ObjectType.IsSameOrParentOf(objectType))
                {
                    var predicate = builder.MakeIsPredicate(table, objectType);

                    if (predicate.GetType() != typeof(SqlPredicate.Expr))
                    {
                        sequence.SelectQuery.Where.SearchCondition.Conditions.Add(new SqlCondition(false, predicate));
                    }
                }
            }
コード例 #11
0
 public IBuildContext BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return(BuildMethodCall(builder, (MethodCallExpression)buildInfo.Expression, buildInfo));
 }
コード例 #12
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();

            var expr = collectionSelector.Body.Unwrap();

            DefaultIfEmptyBuilder.DefaultIfEmptyContext?defaultIfEmpty = null;
            if (expr is MethodCallExpression mc && AllJoinsBuilder.IsMatchingMethod(mc, true))
            {
                defaultIfEmpty = new DefaultIfEmptyBuilder.DefaultIfEmptyContext(buildInfo.Parent, sequence, null);
                sequence       = new SubQueryContext(defaultIfEmpty);

                defaultIfEmpty.Disabled = true;
            }
コード例 #13
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return
         (methodCall.IsQueryable("SelectMany") &&
          methodCall.Arguments.Count == 3 &&
          ((LambdaExpression)methodCall.Arguments[1].Unwrap()).Parameters.Count == 1);
 }
コード例 #14
0
 public RawSqlContext(ExpressionBuilder builder, BuildInfo buildInfo, Type originalType, string sql, params ISqlExpression[] parameters)
     : base(builder, buildInfo, new SqlRawSqlTable(builder.MappingSchema, originalType, sql, parameters))
 {
 }
コード例 #15
0
        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.GetGenericArgumentsEx()[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.IsGenericTypeEx() && 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.SelectQuery.Select.IsDistinct ||
                sequence.SelectQuery.GroupBy.Items.Count > 0 ||
                groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SqlColumn)))
            {
                sequence = new SubQueryContext(sequence);
                key      = new KeyContext(buildInfo.Parent, keySelector, sequence);
                groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);
            }

            foreach (var sql in groupSql)
            {
                sequence.SelectQuery.GroupBy.Expr(sql.Sql);
            }

//			new QueryVisitor().Visit(sequence.SelectQuery.From, e =>
//			{
//				if (e.ElementType == QueryElementType.JoinedTable)
//				{
//					var jt = (SelectQuery.JoinedTable)e;
//					if (jt.JoinType == SelectQuery.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);

            Debug.WriteLine("BuildMethodCall GroupBy:\n" + groupBy.SelectQuery);

            return(groupBy);
        }
コード例 #16
0
 protected abstract bool          CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo);
コード例 #17
0
            public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo)
            {
                if (expression == null && buildInfo != null)
                {
                    if (buildInfo.Parent is SelectManyBuilder.SelectManyContext)
                    {
                        var sm     = (SelectManyBuilder.SelectManyContext)buildInfo.Parent;
                        var ctype  = typeof(ContextHelper <>).MakeGenericType(_key.Lambda.Parameters[0].Type);
                        var helper = (IContextHelper)Activator.CreateInstance(ctype);
                        var expr   = helper.GetContext(
                            Builder.MappingSchema,
                            Sequence.Expression,
                            _key.Lambda.Parameters[0],
                            Expression.PropertyOrField(sm.Lambda.Parameters[0], "Key"),
                            _key.Lambda.Body);

                        return(Builder.BuildSequence(new BuildInfo(buildInfo, expr)));
                    }

                    //if (buildInfo.Parent == this)
                    {
                        var ctype  = typeof(ContextHelper <>).MakeGenericType(_key.Lambda.Parameters[0].Type);
                        var helper = (IContextHelper)Activator.CreateInstance(ctype);
                        var expr   = helper.GetContext(
                            Builder.MappingSchema,
                            _sequenceExpr,
                            _key.Lambda.Parameters[0],
                            Expression.PropertyOrField(buildInfo.Expression, "Key"),
                            _key.Lambda.Body);

                        var ctx = Builder.BuildSequence(new BuildInfo(buildInfo, expr));

                        ctx.SelectQuery.Properties.Add(Tuple.Create("from_group_by", SelectQuery));

                        return(ctx);
                    }

                    //return this;
                }

                if (level != 0)
                {
                    var levelExpression = expression.GetLevelExpression(Builder.MappingSchema, level);

                    if (levelExpression.NodeType == ExpressionType.MemberAccess)
                    {
                        var ma = (MemberExpression)levelExpression;

                        if (ma.Member.Name == "Key" && ma.Member.DeclaringType == _groupingType)
                        {
                            return(ReferenceEquals(levelExpression, expression) ?
                                   _key.GetContext(null, 0, buildInfo) :
                                   _key.GetContext(expression, level + 1, buildInfo));
                        }
                    }
                }

                throw new NotImplementedException();
            }
コード例 #18
0
 protected abstract IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo);
コード例 #19
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.Arguments.Count == 2 && methodCall.IsQueryable("Concat", "Union"));
 }
コード例 #20
0
ファイル: InsertBuilder.cs プロジェクト: exileDev/linq2db
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            var isSubQuery = sequence.SelectQuery.Select.IsDistinct;

            if (isSubQuery)
            {
                sequence = new SubQueryContext(sequence);
            }

            if (!(sequence.Statement is SqlInsertStatement insertStatement))
            {
                insertStatement    = new SqlInsertStatement(sequence.SelectQuery);
                sequence.Statement = insertStatement;
            }

            var insertType = InsertContext.InsertType.Insert;

            switch (methodCall.Method.Name)
            {
            case nameof(LinqExtensions.Insert): insertType = InsertContext.InsertType.Insert;             break;

            case nameof(LinqExtensions.InsertWithIdentity): insertType = InsertContext.InsertType.InsertWithIdentity; break;

            case nameof(LinqExtensions.InsertWithOutput): insertType = InsertContext.InsertType.InsertOutput;       break;

            case nameof(LinqExtensions.InsertWithOutputInto): insertType = InsertContext.InsertType.InsertOutputInto;   break;
            }
コード例 #21
0
        protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            if (!methodCall.IsQueryable(MethodNames))
            {
                return(false);
            }

            var body = ((LambdaExpression)methodCall.Arguments[1].Unwrap()).Body.Unwrap();

            if (body.NodeType == ExpressionType.MemberInit)
            {
                var  mi = (MemberInitExpression)body;
                bool throwExpr;

                if (mi.NewExpression.Arguments.Count > 0 || mi.Bindings.Count == 0)
                {
                    throwExpr = true;
                }
                else
                {
                    throwExpr = mi.Bindings.Any(b => b.BindingType != MemberBindingType.Assignment);
                }

                if (throwExpr)
                {
                    throw new NotSupportedException($"Explicit construction of entity type '{body.Type}' in order by is not allowed.");
                }
            }

            return(true);
        }
コード例 #22
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.IsQueryable("All", "Any"));
 }
コード例 #23
0
        protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            if (methodCall.IsQueryable(MethodNames) || methodCall.IsAsyncExtension(MethodNames))
            {
                return(true);
            }

            return(false);
        }
コード例 #24
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])
            {
                CopyTable = true
            });

            if (methodCall.Arguments.Count == 2)
            {
                if (sequence.SelectQuery.Select.TakeValue != null ||
                    sequence.SelectQuery.Select.SkipValue != null)
                {
                    sequence = new SubQueryContext(sequence);
                }

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

                if (methodCall.Method.Name == "All")
                {
                    condition = Expression.Lambda(Expression.Not(condition.Body), condition.Name, condition.Parameters);
                }

                sequence = builder.BuildWhere(buildInfo.Parent, sequence, condition, true);
                sequence.SetAlias(condition.Parameters[0].Name);
            }

            return(new AllAnyContext(buildInfo.Parent, methodCall, sequence));
        }
コード例 #25
0
 protected override SequenceConvertInfo?Convert(
     ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression?param)
 {
     return(null);
 }
コード例 #26
0
ファイル: ArrayBuilder.cs プロジェクト: bgrainger/linq2db
 public bool CanBuild(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return(Find(builder, buildInfo, (i, t) => i) > 0);
 }
コード例 #27
0
 public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo)
 {
     throw new NotImplementedException();
 }
コード例 #28
0
 public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo)
 {
     return(base.GetContext(expression, level, buildInfo));
 }
コード例 #29
0
ファイル: ContainsBuilder.cs プロジェクト: yallie/linq2db
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence         = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var buildInStatement = false;

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

            return(new ContainsContext(buildInfo.Parent, methodCall, sequence, buildInStatement));
        }
コード例 #30
0
ファイル: SelectManyBuilder.cs プロジェクト: vanbukin/linq2db
        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.HasUnion || !sequence.SelectQuery.IsSimple)
            {
                sequence = new SubQueryContext(sequence);
            }

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

            context.SetAlias(collectionSelector.Parameters[0].Name);

            var expr = collectionSelector.Body.Unwrap();

            var collectionInfo = new BuildInfo(context, expr, new SelectQuery());
            var collection     = builder.BuildSequence(collectionInfo);

            if (resultSelector.Parameters.Count > 1)
            {
                collection.SetAlias(resultSelector.Parameters[1].Name);
            }

            var leftJoin = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext || collectionInfo.JoinType == JoinType.Left;
            var sql      = collection.SelectQuery;

            var sequenceTables = new HashSet <ISqlTableSource>(sequence.SelectQuery.From.Tables[0].GetTables());
            var newQuery       = null != QueryVisitor.Find(sql, e => e == collectionInfo.SelectQuery);
            var crossApply     = null != 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(((SqlColumn)e).Parent));

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

                groupJoin.SelectQuery.From.Tables[0].Joins[0].JoinType = 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 ? JoinType.OuterApply : JoinType.CrossApply;

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

                            ((ISqlExpressionWalkable)collection.SelectQuery.Where).Walk(false, e =>
                            {
                                if (e is SqlColumn column)
                                {
                                    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 = sql.OuterApply();
                    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));
                }
            }

            void MoveSearchConditionsToJoin(SqlFromClause.Join join)
            {
                var tableSources = new HashSet <ISqlTableSource>();

                ((ISqlExpressionWalkable)sql.Where.SearchCondition).Walk(false, e =>
                {
                    if (e is ISqlTableSource ts && !tableSources.Contains(ts))
                    {
                        tableSources.Add(ts);
                    }
                    return(e);
                });

                bool ContainsTable(ISqlTableSource tbl, IQueryElement qe)
                {
                    return(null != QueryVisitor.Find(qe, e =>
                                                     e == tbl ||
                                                     e.ElementType == QueryElementType.SqlField && tbl == ((SqlField)e).Table ||
                                                     e.ElementType == QueryElementType.Column && tbl == ((SqlColumn)e).Parent));
                }

                var conditions = sql.Where.SearchCondition.Conditions;

                if (conditions.Count > 0)
                {
                    for (var i = conditions.Count - 1; i >= 0; i--)
                    {
                        var condition = conditions[i];

                        if (!tableSources.Any(ts => ContainsTable(ts, condition)))
                        {
                            join.JoinedTable.Condition.Conditions.Insert(0, condition);
                            conditions.RemoveAt(i);
                        }
                    }
                }
            }