internal static ObjectQueryState Top(
            ObjectQueryState query,
            string alias,
            string count,
            ObjectParameter[] parameters)
        {
            int           length               = count.Length;
            string        commandText          = EntitySqlQueryBuilder.GetCommandText(query);
            bool          allowsLimitSubclause = ((EntitySqlQueryState)query).AllowsLimitSubclause;
            StringBuilder queryText            = new StringBuilder(!allowsLimitSubclause ? length + ("SELECT VALUE TOP(\r\n".Length + "\r\n) ".Length + alias.Length + "\r\nFROM (\r\n".Length + commandText.Length + "\r\n) AS ".Length + alias.Length) : length + (commandText.Length + "\r\nLIMIT\r\n".Length));

            if (allowsLimitSubclause)
            {
                queryText.Append(commandText);
                queryText.Append("\r\nLIMIT\r\n");
                queryText.Append(count);
            }
            else
            {
                queryText.Append("SELECT VALUE TOP(\r\n");
                queryText.Append(count);
                queryText.Append("\r\n) ");
                queryText.Append(alias);
                queryText.Append("\r\nFROM (\r\n");
                queryText.Append(commandText);
                queryText.Append("\r\n) AS ");
                queryText.Append(alias);
            }
            return(EntitySqlQueryBuilder.NewBuilderQuery(query, query.ElementType, queryText, query.Span, (IEnumerable <ObjectParameter>)EntitySqlQueryBuilder.MergeParameters(query.ObjectContext, query.Parameters, parameters)));
        }
        private static ObjectQueryState BuildSelectOrSelectValue(
            ObjectQueryState query, string alias, string projection, ObjectParameter[] parameters, string projectOp, Type elementType)
        {
            DebugCheck.NotEmpty(alias);
            DebugCheck.NotEmpty(projection);

            var queryText = GetCommandText(query);

            // Build the new query string - "<project op> <projection> FROM (<this query>) AS <alias>"
            var queryLength = projectOp.Length +
                              projection.Length +
                              _fromOp.Length +
                              queryText.Length +
                              _asOp.Length +
                              alias.Length;

            var builder = new StringBuilder(queryLength);

            builder.Append(projectOp);
            builder.Append(projection);
            builder.Append(_fromOp);
            builder.Append(queryText);
            builder.Append(_asOp);
            builder.Append(alias);

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span should not be carried over from a Select or SelectValue operation.
            return(NewBuilderQuery(query, elementType, builder, null, MergeParameters(query.ObjectContext, query.Parameters, parameters)));
        }
        internal static ObjectQueryState OfType(ObjectQueryState query, EdmType newType, Type clrOfType)
        {
            Debug.Assert(newType != null, "OfType cannot be null");
            Debug.Assert(Helper.IsEntityType(newType) || Helper.IsComplexType(newType), "OfType must be Entity or Complex type");

            var queryText = GetCommandText(query);

            // Build the new query string - "OFTYPE((<query>), [<type namespace>].[<type name>])"
            var queryLength = _ofTypeProlog.Length +
                              queryText.Length +
                              _ofTypeInfix.Length +
                              newType.NamespaceName.Length +
                              (!string.IsNullOrEmpty(newType.NamespaceName) ? _ofTypeInfix2.Length : 0) +
                              newType.Name.Length +
                              _ofTypeEpilog.Length;

            var builder = new StringBuilder(queryLength);

            builder.Append(_ofTypeProlog);
            builder.Append(queryText);
            builder.Append(_ofTypeInfix);
            if (!string.IsNullOrEmpty(newType.NamespaceName))
            {
                builder.Append(newType.NamespaceName);
                builder.Append(_ofTypeInfix2);
            }
            builder.Append(newType.Name);
            builder.Append(_ofTypeEpilog);

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span is carried over, no adjustment is needed
            return(NewBuilderQuery(query, clrOfType, builder, query.Span, ObjectParameterCollection.DeepCopy(query.Parameters)));
        }
        private static ObjectQueryState BuildOrderByOrWhere(
            ObjectQueryState query,
            string alias,
            string predicateOrKeys,
            ObjectParameter[] parameters,
            string op,
            string skipCount,
            bool allowsLimit)
        {
            string commandText = EntitySqlQueryBuilder.GetCommandText(query);
            int    capacity    = "SELECT VALUE ".Length + alias.Length + "\r\nFROM (\r\n".Length + commandText.Length + "\r\n) AS ".Length + alias.Length + op.Length + predicateOrKeys.Length;

            if (skipCount != null)
            {
                capacity += "\r\nSKIP\r\n".Length + skipCount.Length;
            }
            StringBuilder queryText = new StringBuilder(capacity);

            queryText.Append("SELECT VALUE ");
            queryText.Append(alias);
            queryText.Append("\r\nFROM (\r\n");
            queryText.Append(commandText);
            queryText.Append("\r\n) AS ");
            queryText.Append(alias);
            queryText.Append(op);
            queryText.Append(predicateOrKeys);
            if (skipCount != null)
            {
                queryText.Append("\r\nSKIP\r\n");
                queryText.Append(skipCount);
            }
            return(EntitySqlQueryBuilder.NewBuilderQuery(query, query.ElementType, queryText, allowsLimit, query.Span, (IEnumerable <ObjectParameter>)EntitySqlQueryBuilder.MergeParameters(query.ObjectContext, query.Parameters, parameters)));
        }
 internal static ObjectQueryState Select(
     ObjectQueryState query,
     string alias,
     string projection,
     ObjectParameter[] parameters)
 {
     return(EntitySqlQueryBuilder.BuildSelectOrSelectValue(query, alias, projection, parameters, "SELECT ", typeof(DbDataRecord)));
 }
 internal static ObjectQueryState OrderBy(
     ObjectQueryState query,
     string alias,
     string keys,
     ObjectParameter[] parameters)
 {
     return(EntitySqlQueryBuilder.BuildOrderByOrWhere(query, alias, keys, parameters, "\r\nORDER BY\r\n", (string)null, true));
 }
 internal static ObjectQueryState Where(
     ObjectQueryState query,
     string alias,
     string predicate,
     ObjectParameter[] parameters)
 {
     return(EntitySqlQueryBuilder.BuildOrderByOrWhere(query, alias, predicate, parameters, "\r\nWHERE\r\n", (string)null, false));
 }
        internal static ObjectQueryState Intersect(
            ObjectQueryState leftQuery,
            ObjectQueryState rightQuery)
        {
            Span newSpan = Span.CopyUnion(leftQuery.Span, rightQuery.Span);

            return(EntitySqlQueryBuilder.BuildSetOp(leftQuery, rightQuery, newSpan, "\r\n) INTERSECT (\r\n"));
        }
        internal static ObjectQueryState UnionAll(ObjectQueryState leftQuery, ObjectQueryState rightQuery)
        {
            // Ensure the Spans of the query arguments are merged into the new query's Span.
            var newSpan = Span.CopyUnion(leftQuery.Span, rightQuery.Span);

            // Call the SetOp helper.
            return(BuildSetOp(leftQuery, rightQuery, newSpan, _unionAllOp));
        }
        internal static ObjectQueryState UnionAll(
            ObjectQueryState leftQuery,
            ObjectQueryState rightQuery)
        {
            Span newSpan = Span.CopyUnion(leftQuery.Span, rightQuery.Span);

            return(EntitySqlQueryBuilder.BuildSetOp(leftQuery, rightQuery, newSpan, "\r\n) UNION ALL (\r\n"));
        }
Exemple #11
0
        // <summary>
        // Sets the values the <see cref="PlanCachingEnabled" /> and <see cref="UserSpecifiedMergeOption" /> properties on
        // <paramref name="other" /> to match the values of the corresponding properties on this instance.
        // </summary>
        // <param name="other"> The query state to which this instances settings should be applied. </param>
        internal void ApplySettingsTo(ObjectQueryState other)
        {
            other.PlanCachingEnabled       = PlanCachingEnabled;
            other.UserSpecifiedMergeOption = UserSpecifiedMergeOption;

            // _cachedPlan is intentionally not copied over - since the parameters of 'other' would have to be locked as
            // soon as its execution plan was set, and that may not be appropriate at the time ApplySettingsTo is called.
        }
 internal static ObjectQueryState SelectValue(
     ObjectQueryState query,
     string alias,
     string projection,
     ObjectParameter[] parameters,
     Type projectedType)
 {
     return(EntitySqlQueryBuilder.BuildSelectOrSelectValue(query, alias, projection, parameters, "SELECT VALUE ", projectedType));
 }
 private static ObjectQueryState NewBuilderQuery(
     ObjectQueryState sourceQuery,
     Type elementType,
     StringBuilder queryText,
     Span newSpan,
     IEnumerable <ObjectParameter> enumerableParams)
 {
     return(EntitySqlQueryBuilder.NewBuilderQuery(sourceQuery, elementType, queryText, false, newSpan, enumerableParams));
 }
        internal static ObjectQueryState Distinct(ObjectQueryState query)
        {
            string        commandText = EntitySqlQueryBuilder.GetCommandText(query);
            StringBuilder queryText   = new StringBuilder("SET(\r\n".Length + commandText.Length + "\r\n)".Length);

            queryText.Append("SET(\r\n");
            queryText.Append(commandText);
            queryText.Append("\r\n)");
            return(EntitySqlQueryBuilder.NewBuilderQuery(query, query.ElementType, queryText, query.Span, (IEnumerable <ObjectParameter>)ObjectParameterCollection.DeepCopy(query.Parameters)));
        }
        private static string GetCommandText(ObjectQueryState query)
        {
            string commandText = (string)null;

            if (!query.TryGetCommandText(out commandText))
            {
                throw new NotSupportedException(Strings.ObjectQuery_QueryBuilder_NotSupportedLinqSource);
            }
            return(commandText);
        }
        internal static ObjectQueryState Top(ObjectQueryState query, string alias, string count, ObjectParameter[] parameters)
        {
            var queryLength  = count.Length;
            var queryText    = GetCommandText(query);
            var limitAllowed = ((EntitySqlQueryState)query).AllowsLimitSubclause;

            if (limitAllowed)
            {
                // Build the new query string:
                // <this query> LIMIT <count>
                queryLength += (queryText.Length +
                                _limitOp.Length
                                // + count.Length is added above
                                );
            }
            else
            {
                // Build the new query string:
                // "SELECT VALUE TOP(<count>) <alias> FROM (<this query>) AS <alias>"
                queryLength += (_topOp.Length +
                                // count.Length + is added above
                                _topInfix.Length +
                                alias.Length +
                                _fromOp.Length +
                                queryText.Length +
                                _asOp.Length +
                                alias.Length);
            }

            var builder = new StringBuilder(queryLength);

            if (limitAllowed)
            {
                builder.Append(queryText);
                builder.Append(_limitOp);
                builder.Append(count);
            }
            else
            {
                builder.Append(_topOp);
                builder.Append(count);
                builder.Append(_topInfix);
                builder.Append(alias);
                builder.Append(_fromOp);
                builder.Append(queryText);
                builder.Append(_asOp);
                builder.Append(alias);
            }

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span is carried over, no adjustment is needed.
            return(NewBuilderQuery(
                       query, query.ElementType, builder, query.Span, MergeParameters(query.ObjectContext, query.Parameters, parameters)));
        }
        private static ObjectQueryState BuildOrderByOrWhere(
            ObjectQueryState query, string alias, string predicateOrKeys, ObjectParameter[] parameters, string op, string skipCount,
            bool allowsLimit)
        {
            DebugCheck.NotEmpty(alias);
            DebugCheck.NotEmpty(predicateOrKeys);
            Debug.Assert(null == skipCount || op == _orderByOp, "Skip clause used with WHERE operator?");

            var queryText = GetCommandText(query);

            // Build the new query string:
            // Either: "SELECT VALUE <alias> FROM (<this query>) AS <alias> WHERE <predicate>"
            //  (for Where)
            // Or:  "SELECT VALUE <alias> FROM (<this query>) AS <alias> ORDER BY <keys> <optional: SKIP <skip>>"
            // Depending on the value of 'op'
            var queryLength = _selectValueOp.Length +
                              alias.Length +
                              _fromOp.Length +
                              queryText.Length +
                              _asOp.Length +
                              alias.Length +
                              op.Length +
                              predicateOrKeys.Length;

            if (skipCount != null)
            {
                queryLength += (_skipOp.Length + skipCount.Length);
            }

            var builder = new StringBuilder(queryLength);

            builder.Append(_selectValueOp);
            builder.Append(alias);
            builder.Append(_fromOp);
            builder.Append(queryText);
            builder.Append(_asOp);
            builder.Append(alias);
            builder.Append(op);
            builder.Append(predicateOrKeys);
            if (skipCount != null)
            {
                builder.Append(_skipOp);
                builder.Append(skipCount);
            }

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span is carried over, no adjustment is needed.
            return(NewBuilderQuery(
                       query, query.ElementType, builder, allowsLimit, query.Span,
                       MergeParameters(query.ObjectContext, query.Parameters, parameters)));
        }
        internal static ObjectQueryState Distinct(ObjectQueryState query)
        {
            // Build the new query string - "SET(<this query>)"
            var queryText = GetCommandText(query);
            var builder   = new StringBuilder(_distinctProlog.Length + queryText.Length + _distinctEpilog.Length);

            builder.Append(_distinctProlog);
            builder.Append(queryText);
            builder.Append(_distinctEpilog);

            // Span is carried over, no adjustment is needed

            return(NewBuilderQuery(query, query.ElementType, builder, query.Span, ObjectParameterCollection.DeepCopy(query.Parameters)));
        }
        private static ObjectQueryState BuildSelectOrSelectValue(
            ObjectQueryState query,
            string alias,
            string projection,
            ObjectParameter[] parameters,
            string projectOp,
            Type elementType)
        {
            string        commandText = EntitySqlQueryBuilder.GetCommandText(query);
            StringBuilder queryText   = new StringBuilder(projectOp.Length + projection.Length + "\r\nFROM (\r\n".Length + commandText.Length + "\r\n) AS ".Length + alias.Length);

            queryText.Append(projectOp);
            queryText.Append(projection);
            queryText.Append("\r\nFROM (\r\n");
            queryText.Append(commandText);
            queryText.Append("\r\n) AS ");
            queryText.Append(alias);
            return(EntitySqlQueryBuilder.NewBuilderQuery(query, elementType, queryText, (Span)null, (IEnumerable <ObjectParameter>)EntitySqlQueryBuilder.MergeParameters(query.ObjectContext, query.Parameters, parameters)));
        }
        internal static ObjectQueryState GroupBy(
            ObjectQueryState query,
            string alias,
            string keys,
            string projection,
            ObjectParameter[] parameters)
        {
            string        commandText = EntitySqlQueryBuilder.GetCommandText(query);
            StringBuilder queryText   = new StringBuilder("SELECT ".Length + projection.Length + "\r\nFROM (\r\n".Length + commandText.Length + "\r\n) AS ".Length + alias.Length + "\r\nGROUP BY\r\n".Length + keys.Length);

            queryText.Append("SELECT ");
            queryText.Append(projection);
            queryText.Append("\r\nFROM (\r\n");
            queryText.Append(commandText);
            queryText.Append("\r\n) AS ");
            queryText.Append(alias);
            queryText.Append("\r\nGROUP BY\r\n");
            queryText.Append(keys);
            return(EntitySqlQueryBuilder.NewBuilderQuery(query, typeof(DbDataRecord), queryText, (Span)null, (IEnumerable <ObjectParameter>)EntitySqlQueryBuilder.MergeParameters(query.ObjectContext, query.Parameters, parameters)));
        }
        internal static ObjectQueryState OfType(
            ObjectQueryState query,
            EdmType newType,
            Type clrOfType)
        {
            string        commandText = EntitySqlQueryBuilder.GetCommandText(query);
            StringBuilder queryText   = new StringBuilder("OFTYPE(\r\n(\r\n".Length + commandText.Length + "\r\n),\r\n[".Length + newType.NamespaceName.Length + (!string.IsNullOrEmpty(newType.NamespaceName) ? "].[".Length : 0) + newType.Name.Length + "]\r\n)".Length);

            queryText.Append("OFTYPE(\r\n(\r\n");
            queryText.Append(commandText);
            queryText.Append("\r\n),\r\n[");
            if (!string.IsNullOrEmpty(newType.NamespaceName))
            {
                queryText.Append(newType.NamespaceName);
                queryText.Append("].[");
            }
            queryText.Append(newType.Name);
            queryText.Append("]\r\n)");
            return(EntitySqlQueryBuilder.NewBuilderQuery(query, clrOfType, queryText, query.Span, (IEnumerable <ObjectParameter>)ObjectParameterCollection.DeepCopy(query.Parameters)));
        }
        private static ObjectQueryState BuildSetOp(
            ObjectQueryState leftQuery,
            ObjectQueryState rightQuery,
            Span newSpan,
            string setOp)
        {
            string commandText1 = EntitySqlQueryBuilder.GetCommandText(leftQuery);
            string commandText2 = EntitySqlQueryBuilder.GetCommandText(rightQuery);

            if (!object.ReferenceEquals((object)leftQuery.ObjectContext, (object)rightQuery.ObjectContext))
            {
                throw new ArgumentException(Strings.ObjectQuery_QueryBuilder_InvalidQueryArgument, "query");
            }
            StringBuilder queryText = new StringBuilder("(\r\n".Length + commandText1.Length + setOp.Length + commandText2.Length + "\r\n)".Length);

            queryText.Append("(\r\n");
            queryText.Append(commandText1);
            queryText.Append(setOp);
            queryText.Append(commandText2);
            queryText.Append("\r\n)");
            return(EntitySqlQueryBuilder.NewBuilderQuery(leftQuery, leftQuery.ElementType, queryText, newSpan, (IEnumerable <ObjectParameter>)EntitySqlQueryBuilder.MergeParameters(leftQuery.Parameters, rightQuery.Parameters)));
        }
        private static ObjectQueryState NewBuilderQuery(
            ObjectQueryState sourceQuery, Type elementType, StringBuilder queryText, bool allowsLimit, Span newSpan,
            IEnumerable <ObjectParameter> enumerableParams)
        {
            var queryParams = enumerableParams as ObjectParameterCollection;

            if (queryParams == null &&
                enumerableParams != null)
            {
                queryParams = new ObjectParameterCollection(sourceQuery.ObjectContext.Perspective);
                foreach (var objectParam in enumerableParams)
                {
                    queryParams.Add(objectParam);
                }
            }

            var newState = new EntitySqlQueryState(
                elementType, queryText.ToString(), allowsLimit, sourceQuery.ObjectContext, queryParams, newSpan);

            sourceQuery.ApplySettingsTo(newState);

            return(newState);
        }
        private static ObjectQueryState BuildSetOp(ObjectQueryState leftQuery, ObjectQueryState rightQuery, Span newSpan, string setOp)
        {
            // Assert that the arguments aren't null (should have been verified by ObjectQuery)
            DebugCheck.NotNull(leftQuery);
            DebugCheck.NotNull(rightQuery);
            Debug.Assert(
                leftQuery.ElementType.Equals(rightQuery.ElementType),
                "Incompatible element types in arguments to Except<T>/Intersect<T>/Union<T>/UnionAll<T>?");

            // Retrieve the left and right arguments to the set operation -
            // this will throw if either input query is not an Entity-SQL query.
            var left  = GetCommandText(leftQuery);
            var right = GetCommandText(rightQuery);

            // ObjectQuery arguments must be associated with the same ObjectContext instance as the implemented query
            if (!ReferenceEquals(leftQuery.ObjectContext, rightQuery.ObjectContext))
            {
                throw new ArgumentException(Strings.ObjectQuery_QueryBuilder_InvalidQueryArgument, "query");
            }

            // Create a string builder only large enough to contain the new query text
            var queryLength = _setOpProlog.Length + left.Length + setOp.Length + right.Length + _setOpEpilog.Length;
            var builder     = new StringBuilder(queryLength);

            // Build the new query
            builder.Append(_setOpProlog);
            builder.Append(left);
            builder.Append(setOp);
            builder.Append(right);
            builder.Append(_setOpEpilog);

            // Create a new query implementation and apply the state of this implementation to it.
            // The Span of the query argument will be merged into the new query's Span by the caller, iff the Set Op is NOT Except.
            // See the Except, Intersect, Union and UnionAll methods in this class for examples.
            return(NewBuilderQuery(
                       leftQuery, leftQuery.ElementType, builder, newSpan, MergeParameters(leftQuery.Parameters, rightQuery.Parameters)));
        }
        internal static ObjectQueryState GroupBy(
            ObjectQueryState query, string alias, string keys, string projection, ObjectParameter[] parameters)
        {
            DebugCheck.NotEmpty(alias);
            DebugCheck.NotEmpty(keys);
            DebugCheck.NotEmpty(projection);

            var queryText = GetCommandText(query);

            // Build the new query string:
            // "SELECT <projection> FROM (<this query>) AS <alias> GROUP BY <keys>"
            var queryLength = _selectOp.Length +
                              projection.Length +
                              _fromOp.Length +
                              queryText.Length +
                              _asOp.Length +
                              alias.Length +
                              _groupByOp.Length +
                              keys.Length;

            var builder = new StringBuilder(queryLength);

            builder.Append(_selectOp);
            builder.Append(projection);
            builder.Append(_fromOp);
            builder.Append(queryText);
            builder.Append(_asOp);
            builder.Append(alias);
            builder.Append(_groupByOp);
            builder.Append(keys);

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span should not be carried over from a GroupBy operation.
            return(NewBuilderQuery(
                       query, typeof(DbDataRecord), builder, null, MergeParameters(query.ObjectContext, query.Parameters, parameters)));
        }
 internal static ObjectQueryState Where(ObjectQueryState query, string alias, string predicate, ObjectParameter[] parameters)
 {
     return(BuildOrderByOrWhere(query, alias, predicate, parameters, _whereOp, null, false));
 }
 internal static ObjectQueryState OrderBy(ObjectQueryState query, string alias, string keys, ObjectParameter[] parameters)
 {
     return(BuildOrderByOrWhere(query, alias, keys, parameters, _orderByOp, null, true));
 }
        internal static ObjectQueryState Skip(ObjectQueryState query, string alias, string keys, string count, ObjectParameter[] parameters)
        {
            DebugCheck.NotEmpty(count);

            return(BuildOrderByOrWhere(query, alias, keys, parameters, _orderByOp, count, true));
        }
 internal static ObjectQueryState Select(ObjectQueryState query, string alias, string projection, ObjectParameter[] parameters)
 {
     return(BuildSelectOrSelectValue(query, alias, projection, parameters, _selectOp, typeof(DbDataRecord)));
 }
 internal static ObjectQueryState SelectValue(
     ObjectQueryState query, string alias, string projection, ObjectParameter[] parameters, Type projectedType)
 {
     return(BuildSelectOrSelectValue(query, alias, projection, parameters, _selectValueOp, projectedType));
 }