diff --git a/src/Microsoft.OData.Client/DataServiceQueryExtensions.cs b/src/Microsoft.OData.Client/DataServiceQueryExtensions.cs
new file mode 100644
index 0000000000..e2ff8e4d35
--- /dev/null
+++ b/src/Microsoft.OData.Client/DataServiceQueryExtensions.cs
@@ -0,0 +1,1035 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+namespace Microsoft.OData.Client
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Linq.Expressions;
+
+ using Microsoft.Spatial;
+
+ ///
+ /// Extension methods for
+ ///
+ ///
+ /// We discussed three options when we decided to implement extension methods for that are analogous to the LINQ extensions
+ /// for , but that preserve the type. They were:
+ /// 1. Implement an ExecuteBatch overload on that would take s as parameters
+ /// 2. Implement a Query extension method that would preserve the type and take in the query
+ /// that should be applied to the , something like:
+ /// public static DataServiceQuery>TResult> Query<>TElement, TResult>(
+ /// this DataServiceQuery>TElement> source,
+ /// Func>IQueryable>TElement>, IQueryable>TResult>> query)
+ /// {
+ /// return new DataServiceQuery>TResult>(query(source).Expression, new DataServiceQueryProvider(source.Context));
+ /// }
+ /// 3. Implement the analogous extension methods as we have done
+ ///
+ /// Option 1 has the benefit of being closer to what current callers are doing. Most callers call and then
+ /// pass the resulting s as parameters to . In this way,
+ /// they would follow the same pattern, but if the caller uses a LINQ query on some number of the returned s, their code
+ /// would simply automatically call the new overload for the ExecuteBatch method.
+ ///
+ /// Option 2 has the benefit from the development side that there is a single method that needs to be implemented, and it would support all of the LINQ queries.
+ ///
+ /// Option 3 has the benefit, like option 1, that it is completely transparent to the caller, and it also allows us to preserve the
+ /// type for other cases outside of
+ ///
+ /// We ruled out option 2 because we decided it was important for the solution to be discoverable. There is already a solution to this issue in the
+ /// AddQueryOption method, so having an additional solution that callers won't find was not
+ /// desirable.
+ ///
+ /// We ruled out option 1 because type checks are another reason that callers don't like to use
+ /// . removes the
+ /// typing from the . Option 1 would also strip out the typing. To preserve the type, there would need to be multiple overloads with
+ /// different number of type parameters, like:
+ /// public static DataServiceResponse ExecuteBatch(IQueryable query1)
+ /// {
+ /// ...
+ /// }
+ ///
+ /// public static DataServiceResponse ExecuteBatch>T1, T2>(IQueryable>T1> query1, IQueryable>T2> query2)
+ /// {
+ /// ...
+ /// }
+ ///
+ /// ...
+ /// Even if we ignore the typing issue, the new overload would also assume that the s that it receives were generated by the same
+ /// that the uses. We would have to do this validation at runtime, and errors here would be unintuitive
+ /// for the caller.
+ ///
+ /// Since options 3 preserves the type checks, is highly discoverable by callers, and maintains the current call pattern, we decided it was the best approach.
+ ///
+ public static class DataServiceQueryExtensions
+ {
+ ///
+ /// Concatenates two sequences.
+ ///
+ /// The type of the elements of the input sequences.
+ /// The first sequence to concatenate.
+ /// The sequence to concatenate to the first sequence.
+ /// A that contains the concatenated elements of the two input sequences.
+ /// Thrown if or is
+ public static DataServiceQuery Concat(this DataServiceQuery source1, IEnumerable source2)
+ {
+ return new DataServiceQuery(source1.AsQueryable().Concat(source2).Expression, new DataServiceQueryProvider(source1.Context));
+ }
+
+ ///
+ /// Returns the elements of the specified sequence or the specified value in a singleton collection if the sequence is empty.
+ ///
+ /// The type of the elements of .
+ /// The to return the specified value for if empty.
+ /// The value to return if the sequence is empty.
+ ///
+ /// A that contains if is empty; otherwise,
+ /// .
+ ///
+ /// Thrown if is
+ public static DataServiceQuery DefaultIfEmpty(this DataServiceQuery source, TSource defaultValue)
+ {
+ return new DataServiceQuery(source.AsQueryable().DefaultIfEmpty(defaultValue).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Returns the elements of the specified sequence or the type parameter's default value in a singleton collection if the sequence is empty.
+ ///
+ /// The type of the elements of .
+ /// The to return a default value for if empty.
+ ///
+ /// A that contains () if is empty;
+ /// otherwise, .
+ ///
+ /// Thrown if is
+ public static DataServiceQuery DefaultIfEmpty(this DataServiceQuery source)
+ {
+ return new DataServiceQuery(source.AsQueryable().DefaultIfEmpty().Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Returns distinct elements from a sequence by using a specified to compare values.
+ ///
+ /// The type of the elements of .
+ /// The to remove duplicates from.
+ /// An to compare values.
+ /// A that contains distinct elements from .
+ /// Thrown if or is
+ public static DataServiceQuery Distinct(this DataServiceQuery source, IEqualityComparer comparer)
+ {
+ return new DataServiceQuery(source.AsQueryable().Distinct(comparer).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Returns distinct elements from a sequence by using the default equality comparer to compare values.
+ ///
+ /// The type of the elements of .
+ /// The to remove duplicates from.
+ /// A that contains distinct elements from .
+ /// Thrown if is
+ public static DataServiceQuery Distinct(this DataServiceQuery source)
+ {
+ return new DataServiceQuery(source.AsQueryable().Distinct().Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Produces the set difference of two sequences by using the default equality comparer to compare values.
+ ///
+ /// The type of the elements of the input sequences.
+ /// A whose elements that are not also in will be returned.
+ /// An whose elements that also occur in the first sequence will not appear in the returned sequence.
+ /// A that contains the set difference of the two sequences.
+ /// Thrown if or is
+ public static DataServiceQuery Except(this DataServiceQuery source1, IEnumerable source2)
+ {
+ return new DataServiceQuery(source1.AsQueryable().Except(source2).Expression, new DataServiceQueryProvider(source1.Context));
+ }
+
+ ///
+ /// Produces the set difference of two sequences by using the specified to compare values.
+ ///
+ /// The type of the elements of the input sequences.
+ /// A whose elements that are not also in will be returned.
+ /// An whose elements that also occur in the first sequence will not appear in the returned sequence.
+ /// An to compare values.
+ /// A that contains the set difference of the two sequences.
+ /// Thrown if or is
+ public static DataServiceQuery Except(
+ this DataServiceQuery source1,
+ IEnumerable source2,
+ IEqualityComparer comparer)
+ {
+ return new DataServiceQuery(source1.AsQueryable().Except(source2, comparer).Expression, new DataServiceQueryProvider(source1.Context));
+ }
+
+ ///
+ /// Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. The elements of
+ /// each group are projected by using a specified function.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented in .
+ /// The type of the elements in each .
+ /// The type of the result value returned by .
+ /// A whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to map each source element to an element in an .
+ /// A function to create a result value from each group.
+ ///
+ /// A that has a type argument of and where each element represents a projection over a
+ /// group and its key.
+ ///
+ ///
+ /// Thrown if or or or is
+ ///
+ ///
+ public static DataServiceQuery GroupBy(
+ this DataServiceQuery source,
+ Expression> keySelector,
+ Expression> elementSelector,
+ Expression, TResult>> resultSelector)
+ {
+ return new DataServiceQuery(
+ source.AsQueryable().GroupBy(keySelector, elementSelector, resultSelector).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented in .
+ /// The type of the result value returned by .
+ /// A whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to create a result value from each group.
+ ///
+ /// A that has a type argument of and where each element represents a projection over a
+ /// group and its key.
+ ///
+ ///
+ /// Thrown if or or is
+ ///
+ public static DataServiceQuery GroupBy(
+ this DataServiceQuery source,
+ Expression> keySelector,
+ Expression, TResult>> resultSelector)
+ {
+ return new DataServiceQuery(source.AsQueryable().GroupBy(keySelector, resultSelector).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Groups the elements of a sequence according to a specified key selector function and projects the elements for each group by using a specified function.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented in .
+ /// The type of the elements in each .
+ /// A whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to map each source element to an element in an .
+ ///
+ /// A where each element is a and where each
+ /// contains a sequence of objects of type and a key.
+ ///
+ ///
+ /// Thrown if or or is
+ ///
+ public static DataServiceQuery> GroupBy(
+ this DataServiceQuery source,
+ Expression> keySelector,
+ Expression> elementSelector)
+ {
+ return new DataServiceQuery>(
+ source.AsQueryable().GroupBy(keySelector, elementSelector).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. Keys are compared by
+ /// using a specified comparer and the elements of each group are projected by using a specified function.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented in .
+ /// The type of the elements in each .
+ /// The type of the result value returned by .
+ /// A whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to map each source element to an element in an .
+ /// A function to create a result value from each group.
+ /// A to compare keys.
+ ///
+ /// A that has a type argument of and where each element represents a projection over a
+ /// group and its key.
+ ///
+ ///
+ /// Thrown if or or or or
+ /// is
+ ///
+ public static DataServiceQuery GroupBy(
+ this DataServiceQuery source,
+ Expression> keySelector,
+ Expression> elementSelector,
+ Expression, TResult>> resultSelector,
+ IEqualityComparer comparer)
+ {
+ return new DataServiceQuery(
+ source.AsQueryable().GroupBy(keySelector, elementSelector, resultSelector, comparer).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Groups the elements of a sequence according to a specified key selector function.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented in .
+ /// A whose elements to group.
+ /// A function to extract the key for each element.
+ ///
+ /// A where each element is a and where each
+ /// contains a sequence of objects and a key.
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery> GroupBy(
+ this DataServiceQuery source,
+ Expression> keySelector)
+ {
+ return new DataServiceQuery>(source.AsQueryable().GroupBy(keySelector).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. Keys are compared by
+ /// using a specified comparer.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented in .
+ /// The type of the result value returned by .
+ /// A whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to create a result value from each group.
+ /// An to compare keys.
+ ///
+ /// A that has a type argument of and where each element represents a projection over a
+ /// group and its key.
+ ///
+ ///
+ /// Thrown if or or or is
+ ///
+ ///
+ public static DataServiceQuery GroupBy(
+ this DataServiceQuery source,
+ Expression> keySelector,
+ Expression, TResult>> resultSelector,
+ IEqualityComparer comparer)
+ {
+ return new DataServiceQuery(
+ source.AsQueryable().GroupBy(keySelector, resultSelector, comparer).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Groups the elements of a sequence and projects the elements for each group by using a specified function. Key values are compared by using a specified
+ /// comparer.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented in .
+ /// The type of the elements in each .
+ /// A whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to map each source element to an element in an .
+ /// An to compare keys.
+ ///
+ /// A where each element is a and where each
+ /// contains a sequence of objects of type and a key.
+ ///
+ ///
+ /// Thrown if or or or is
+ ///
+ ///
+ public static DataServiceQuery> GroupBy(
+ this DataServiceQuery source,
+ Expression> keySelector,
+ Expression> elementSelector,
+ IEqualityComparer comparer)
+ {
+ return new DataServiceQuery>(
+ source.AsQueryable().GroupBy(keySelector, elementSelector, comparer).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Groups the elements of a sequence according to a specified key selector function and compares the keys by using a specified comparer.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented in .
+ /// An whose elements to group.
+ /// A function to extract the key for each element.
+ /// An to compare keys.
+ ///
+ /// A where each element is a and where each
+ /// contains a sequence of objects and a key.
+ ///
+ ///
+ /// Thrown if or or is
+ ///
+ public static DataServiceQuery> GroupBy(
+ this DataServiceQuery source,
+ Expression> keySelector,
+ IEqualityComparer comparer)
+ {
+ return new DataServiceQuery>(
+ source.AsQueryable().GroupBy(keySelector, comparer).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Correlates the elements of two sequences based on key equality and groups the results. A specified is used to compare
+ /// keys.
+ ///
+ /// The type of the elements of the first sequence.
+ /// The type of the elements of the second sequence.
+ /// The type of the keys returned by the key selector functions.
+ /// The type of the result elements.
+ /// The first sequence to join.
+ /// The sequence to join to the first sequence.
+ /// A function to extract the join key from each element of the first sequence.
+ /// A function to extract the join key from each element of the second sequence.
+ ///
+ /// A function to create a result element from an element from the first sequence and a collection of matching elements from the second sequence.
+ ///
+ /// A comparer to hash and compare keys.
+ ///
+ /// A that contains elements of type obtained by performing a grouped join on two
+ /// sequences.
+ ///
+ ///
+ /// Thrown if or or or or
+ /// or is
+ ///
+ public static DataServiceQuery GroupJoin(
+ this DataServiceQuery outer,
+ IEnumerable inner,
+ Expression> outerKeySelector,
+ Expression> innerKeySelector,
+ Expression, TResult>> resultSelector,
+ IEqualityComparer comparer)
+ {
+ return new DataServiceQuery(
+ outer.AsQueryable().GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, comparer).Expression,
+ new DataServiceQueryProvider(outer.Context));
+ }
+
+ ///
+ /// Correlates the elements of two sequences based on key equality and groups the results. The default equality comparer is used to compare keys.
+ ///
+ /// The type of the elements of the first sequence.
+ /// The type of the elements of the second sequence.
+ /// The type of the keys returned by the key selector functions.
+ /// The type of the result elements.
+ /// The first sequence to join.
+ /// The sequence to join to the first sequence.
+ /// A function to extract the join key from each element of the first sequence.
+ /// A function to extract the join key from each element of the second sequence.
+ ///
+ /// A function to create a result element from an element from the first sequence and a collection of matching elements from the second sequence.
+ ///
+ ///
+ /// A that contains elements of type obtained by performing a grouped join on two
+ /// sequences.
+ ///
+ ///
+ /// Thrown if or or or or
+ /// is
+ ///
+ public static DataServiceQuery GroupJoin(
+ this DataServiceQuery outer,
+ IEnumerable inner,
+ Expression> outerKeySelector,
+ Expression> innerKeySelector,
+ Expression, TResult>> resultSelector)
+ {
+ return new DataServiceQuery(
+ outer.AsQueryable().GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector).Expression,
+ new DataServiceQueryProvider(outer.Context));
+ }
+
+ ///
+ /// Produces the set intersection of two sequences by using the specified to compare values.
+ ///
+ /// The type of the elements of the input sequences.
+ /// A whose distinct elements that also appear in are returned.
+ /// An whose distinct elements that also appear in the first sequence are returned.
+ /// An to compare values.
+ /// A that contains the set intersection of the two sequences.
+ /// Thrown if or is
+ public static DataServiceQuery Intersect(
+ this DataServiceQuery source1,
+ IEnumerable source2,
+ IEqualityComparer comparer)
+ {
+ return new DataServiceQuery(source1.AsQueryable().Intersect(source2, comparer).Expression, new DataServiceQueryProvider(source1.Context));
+ }
+
+ ///
+ /// Produces the set intersection of two sequences by using the default equality comparer to compare values.
+ ///
+ /// The type of the elements of the input sequences.
+ /// A sequence whose distinct elements that also appear in are returned.
+ /// A sequence whose distinct elements that also appear in the first sequence are returned.
+ /// A sequence that contains the set intersection of the two sequences.
+ /// Thrown if or is
+ public static DataServiceQuery Intersect(this DataServiceQuery source1, IEnumerable source2)
+ {
+ return new DataServiceQuery(source1.AsQueryable().Intersect(source2).Expression, new DataServiceQueryProvider(source1.Context));
+ }
+
+ ///
+ /// Correlates the elements of two sequences based on matching keys. A specified is used to compare keys.
+ ///
+ /// The type of the elements of the first sequence.
+ /// The type of the elements of the second sequence.
+ /// The type of the keys returned by the key selector functions.
+ /// The type of the result elements.
+ /// The first sequence to join.
+ /// The sequence to join to the first sequence.
+ /// A function to extract the join key from each element of the first sequence.
+ /// A function to extract the join key from each element of the second sequence.
+ /// A function to create a result element from two matching elements.
+ /// An to hash and compare keys.
+ ///
+ /// A that has elements of type obtained by performing an inner join on two sequences.
+ ///
+ ///
+ /// Thrown if or or or or
+ /// is
+ ///
+ public static DataServiceQuery Join(
+ this DataServiceQuery outer,
+ IEnumerable inner,
+ Expression> outerKeySelector,
+ Expression> innerKeySelector,
+ Expression> resultSelector,
+ IEqualityComparer comparer)
+ {
+ return new DataServiceQuery(
+ outer.AsQueryable().Join(inner, outerKeySelector, innerKeySelector, resultSelector, comparer).Expression,
+ new DataServiceQueryProvider(outer.Context));
+ }
+
+ ///
+ /// Correlates the elements of two sequences based on matching keys. The default equality comparer is used to compare keys.
+ ///
+ /// The type of the elements of the first sequence.
+ /// The type of the elements of the second sequence.
+ /// The type of the keys returned by the key selector functions.
+ /// The type of the result elements.
+ /// The first sequence to join.
+ /// The sequence to join to the first sequence.
+ /// A function to extract the join key from each element of the first sequence.
+ /// A function to extract the join key from each element of the second sequence.
+ /// A function to create a result element from two matching elements.
+ ///
+ /// A that has elements of type obtained by performing an inner join on two sequences.
+ ///
+ ///
+ /// Thrown if or or or or
+ /// is
+ ///
+ public static DataServiceQuery Join(
+ this DataServiceQuery outer,
+ IEnumerable inner,
+ Expression> outerKeySelector,
+ Expression> innerKeySelector,
+ Expression> resultSelector)
+ {
+ return new DataServiceQuery(
+ outer.AsQueryable().Join(inner, outerKeySelector, innerKeySelector, resultSelector).Expression,
+ new DataServiceQueryProvider(outer.Context));
+ }
+
+ ///
+ /// Sorts the elements of a sequence in ascending order by using a specified comparer.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function that is represented by .
+ /// A sequence of values to order.
+ /// A function to extract a key from an element.
+ /// An to compare keys.
+ /// A whose elements are sorted according to a key.
+ ///
+ /// Thrown if or or is
+ ///
+ public static DataServiceQuery.DataServiceOrderedQuery OrderBy(
+ this DataServiceQuery source,
+ Expression> keySelector,
+ IComparer comparer)
+ {
+ return new DataServiceQuery.DataServiceOrderedQuery(
+ source.AsQueryable().OrderBy(keySelector, comparer).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Sorts the elements of a sequence in ascending order according to a key.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function that is represented by .
+ /// A sequence of values to order.
+ /// A function to extract a key from an element.
+ /// A whose elements are sorted according to a key.
+ /// Thrown if or is
+ public static DataServiceQuery.DataServiceOrderedQuery OrderBy(
+ this DataServiceQuery source,
+ Expression> keySelector)
+ {
+ return new DataServiceQuery.DataServiceOrderedQuery(
+ source.AsQueryable().OrderBy(keySelector).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Sorts the elements of a sequence in descending order according to a key.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function that is represented by .
+ /// A sequence of values to order.
+ /// A function to extract a key from an element.
+ /// A whose elements are sorted in descending order according to a key.
+ /// Thrown if or is
+ public static DataServiceQuery.DataServiceOrderedQuery OrderByDescending(
+ this DataServiceQuery source,
+ Expression> keySelector)
+ {
+ return new DataServiceQuery.DataServiceOrderedQuery(
+ source.AsQueryable().OrderByDescending(keySelector).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Sorts the elements of a sequence in descending order by using a specified comparer.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function that is represented by .
+ /// A sequence of values to order.
+ /// A function to extract a key from an element.
+ /// An to compare keys.
+ /// A whose elements are sorted in descending order according to a key.
+ ///
+ /// Thrown if or or is
+ ///
+ public static DataServiceQuery.DataServiceOrderedQuery OrderByDescending(
+ this DataServiceQuery source,
+ Expression> keySelector,
+ IComparer comparer)
+ {
+ return new DataServiceQuery.DataServiceOrderedQuery(
+ source.AsQueryable().OrderByDescending(keySelector, comparer).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Inverts the order of the elements in a sequence.
+ ///
+ /// The type of the elements of .
+ /// A sequence of values to reverse.
+ /// A whose elements correspond to those of the input sequence in reverse order.
+ /// Thrown if is
+ public static DataServiceQuery Reverse(this DataServiceQuery source)
+ {
+ return new DataServiceQuery(source.AsQueryable().Reverse().Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Projects each element of a sequence into a new form by incorporating the element's index.
+ ///
+ /// The type of the elements of .
+ /// The type of the value returned by the function represented by .
+ /// A sequence of values to project.
+ /// A projection function to apply to each element.
+ ///
+ /// A whose elements are the result of invoking a projection function on each element of .
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery Select(this DataServiceQuery source, Expression> selector)
+ {
+ return new DataServiceQuery(source.AsQueryable().Select(selector).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Projects each element of a sequence into a new form.
+ ///
+ /// The type of the elements of .
+ /// The type of the value returned by the function represented by .
+ /// A sequence of values to project.
+ /// A projection function to apply to each element.
+ ///
+ /// A whose elements are the result of invoking a projection function on each element of .
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery Select(this DataServiceQuery source, Expression> selector)
+ {
+ return new DataServiceQuery(source.AsQueryable().Select(selector).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Projects each element of a sequence to an and combines the resulting sequences into one sequence.
+ ///
+ /// The type of the elements of .
+ /// The type of the elements of the sequence returned by the function represented by .
+ /// A sequence of values to project.
+ /// A projection function to apply to each element.
+ ///
+ /// A whose elements are the result of invoking a one-to-many projection function on each element of the input sequence.
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery SelectMany(
+ this DataServiceQuery source,
+ Expression>> selector)
+ {
+ return new DataServiceQuery(source.AsQueryable().SelectMany(selector).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Projects each element of a sequence to an and combines the resulting sequences into one sequence. The index of each source
+ /// element is used in the projected form of that element.
+ ///
+ /// The type of the elements of .
+ /// The type of the elements of the sequence returned by the function represented by .
+ /// A sequence of values to project.
+ ///
+ /// A projection function to apply to each element; the second parameter of this function represents the index of the source element.
+ ///
+ ///
+ /// A whose elements are the result of invoking a one-to-many projection function on each element of the input sequence.
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery SelectMany(
+ this DataServiceQuery source,
+ Expression>> selector)
+ {
+ return new DataServiceQuery(source.AsQueryable().SelectMany(selector).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Projects each element of a sequence to an that incorporates the index of the source element that produced it. A result selector
+ /// function is invoked on each element of each intermediate sequence, and the resulting values are combined into a single, one-dimensional sequence and
+ /// returned.
+ ///
+ /// The type of the elements of .
+ ///
+ /// The type of the intermediate elements collected by the function represented by .
+ ///
+ /// The type of the elements of the resulting sequence.
+ /// A sequence of values to project.
+ ///
+ /// A projection function to apply to each element of the input sequence; the second parameter of this function represents the index of the source element.
+ ///
+ /// A projection function to apply to each element of each intermediate sequence.
+ ///
+ /// A whose elements are the result of invoking the one-to-many projection function
+ /// on each element of and then mapping each of those sequence elements and their corresponding
+ /// element to a result element.
+ ///
+ ///
+ /// Thrown if or or is
+ ///
+ public static DataServiceQuery SelectMany(
+ this DataServiceQuery source,
+ Expression>> collectionSelector,
+ Expression> resultSelector)
+ {
+ return new DataServiceQuery(
+ source.AsQueryable().SelectMany(collectionSelector, resultSelector).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Projects each element of a sequence to an and invokes a result selector function on each element therein. The resulting values
+ /// from each intermediate sequence are combined into a single, one-dimensional sequence and returned.
+ ///
+ /// The type of the elements of .
+ ///
+ /// The type of the intermediate elements collected by the function represented by .
+ ///
+ /// The type of the elements of the resulting sequence.
+ /// A sequence of values to project.
+ /// A projection function to apply to each element of the input sequence.
+ /// A projection function to apply to each element of each intermediate sequence.
+ ///
+ /// A whose elements are the result of invoking the one-to-many projection function
+ /// on each element of and then mapping each of those sequence elements and their corresponding
+ /// element to a result element.
+ ///
+ ///
+ /// Thrown if or or is
+ ///
+ public static DataServiceQuery SelectMany(
+ this DataServiceQuery source,
+ Expression>> collectionSelector,
+ Expression> resultSelector)
+ {
+ return new DataServiceQuery(
+ source.AsQueryable().SelectMany(collectionSelector, resultSelector).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Bypasses a specified number of elements in a sequence and then returns the remaining elements.
+ ///
+ /// The type of the elements of .
+ /// A to return elements from.
+ /// The number of elements to skip before returning the remaining elements.
+ /// A that contains elements that occur after the specified index in the input sequence.
+ /// Thrown if is
+ public static DataServiceQuery Skip(this DataServiceQuery source, int count)
+ {
+ return new DataServiceQuery(source.AsQueryable().Skip(count).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.
+ ///
+ /// The type of the elements of .
+ /// A to return elements from.
+ /// A function to test each element for a condition.
+ ///
+ /// A that contains elements from starting at the first element in the linear series that does
+ /// not pass the test specified by .
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery SkipWhile(this DataServiceQuery source, Expression> predicate)
+ {
+ return new DataServiceQuery(source.AsQueryable().SkipWhile(predicate).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. The element's index is used in the logic of
+ /// the predicate function.
+ ///
+ /// The type of the elements of .
+ /// A to return elements from.
+ ///
+ /// A function to test each element for a condition; the second parameter of this function represents the index of the source element.
+ ///
+ ///
+ /// A that contains elements from starting at the first element in the linear series that does
+ /// not pass the test specified by .
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery SkipWhile(this DataServiceQuery source, Expression> predicate)
+ {
+ return new DataServiceQuery(source.AsQueryable().SkipWhile(predicate).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Returns a specified number of contiguous elements from the start of a sequence.
+ ///
+ /// The type of the elements of .
+ /// The sequence to return elements from.
+ /// The number of elements to return.
+ /// A that contains the specified number of elements from the start of .
+ /// Thrown if is
+ public static DataServiceQuery Take(this DataServiceQuery source, int count)
+ {
+ return new DataServiceQuery(source.AsQueryable().Take(count).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Returns elements from a sequence as long as a specified condition is true.
+ ///
+ /// The type of the elements of .
+ /// The sequence to return elements from.
+ /// A function to test each element for a condition.
+ ///
+ /// A that contains elements from the input sequence occurring before the element at which the test specified by
+ /// no longer passes.
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery TakeWhile(this DataServiceQuery source, Expression> predicate)
+ {
+ return new DataServiceQuery(source.AsQueryable().TakeWhile(predicate).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function.
+ ///
+ /// The type of the elements of .
+ /// The sequence to return elements from.
+ ///
+ /// A function to test each element for a condition; the second parameter of the function represents the index of the element in the source sequence.
+ ///
+ ///
+ /// A that contains elements from the input sequence occurring before the element at which the test specified by
+ /// no longer passes.
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery TakeWhile(this DataServiceQuery source, Expression> predicate)
+ {
+ return new DataServiceQuery(source.AsQueryable().TakeWhile(predicate).Expression, new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Performs a subsequent ordering of the elements in a sequence in ascending order by using a specified comparer.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented by .
+ /// A that contains elements to sort.
+ /// A function to extract a key from each element.
+ /// An to compare keys.
+ /// A whose elements are sorted according to a key.
+ ///
+ /// Thrown if or or is
+ ///
+ public static DataServiceQuery.DataServiceOrderedQuery ThenBy(
+ this DataServiceQuery.DataServiceOrderedQuery source,
+ Expression> keySelector,
+ IComparer comparer)
+ {
+ return new DataServiceQuery.DataServiceOrderedQuery(
+ source.AsOrderedQueryable().ThenBy(keySelector, comparer).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented by .
+ /// A that contains elements to sort.
+ /// A function to extract a key from each element.
+ /// A whose elements are sorted according to a key.
+ /// Thrown if or is
+ public static DataServiceQuery.DataServiceOrderedQuery ThenBy(
+ this DataServiceQuery.DataServiceOrderedQuery source,
+ Expression> keySelector)
+ {
+ return new DataServiceQuery.DataServiceOrderedQuery(
+ source.AsOrderedQueryable().ThenBy(keySelector).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Performs a subsequent ordering of the elements in a sequence in descending order, according to a key.
+ ///
+ /// The type of the elements of .
+ /// The type of the key returned by the function represented by .
+ /// A that contains elements to sort.
+ /// A function to extract a key from each element.
+ /// A whose elements are sorted in descending order according to a key.
+ /// Thrown if or is
+ public static DataServiceQuery.DataServiceOrderedQuery ThenByDescending(
+ this DataServiceQuery.DataServiceOrderedQuery source,
+ Expression> keySelector)
+ {
+ return new DataServiceQuery.DataServiceOrderedQuery(
+ source.AsOrderedQueryable().ThenByDescending(keySelector).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Performs a subsequent ordering of the elements in a sequence in descending order by using a specified comparer.
+ ///
+ /// The type of the elements of .
+ /// The type of the key that is returned by the function.
+ /// A that contains elements to sort.
+ /// A function to extract a key from each element.
+ /// An to compare keys.
+ /// A collection whose elements are sorted in descending order according to a key.
+ ///
+ /// Thrown if or or is
+ ///
+ public static DataServiceQuery.DataServiceOrderedQuery ThenByDescending(
+ this DataServiceQuery.DataServiceOrderedQuery source,
+ Expression> keySelector,
+ IComparer comparer)
+ {
+ return new DataServiceQuery.DataServiceOrderedQuery(
+ source.AsOrderedQueryable().ThenByDescending(keySelector, comparer).Expression,
+ new DataServiceQueryProvider(source.Context));
+ }
+
+ ///
+ /// Produces the set union of two sequences by using a specified .
+ ///
+ /// The type of the elements of the input sequences.
+ /// A sequence whose distinct elements form the first set for the union operation.
+ /// A sequence whose distinct elements form the second set for the union operation.
+ /// An to compare values.
+ /// A that contains the elements from both input sequences, excluding duplicates.
+ /// Thrown if or is
+ public static DataServiceQuery Union(this DataServiceQuery source1, IEnumerable source2, IEqualityComparer comparer)
+ {
+ return new DataServiceQuery(source1.AsQueryable().Union(source2, comparer).Expression, new DataServiceQueryProvider(source1.Context));
+ }
+
+ ///
+ /// Produces the set union of two sequences by using the default equality comparer.
+ ///
+ /// The type of the elements of the input sequences.
+ /// A sequence whose distinct elements form the first set for the union operation.
+ /// A sequence whose distinct elements form the second set for the union operation.
+ /// A that contains the elements from both input sequences, excluding duplicates.
+ /// Thrown if or is
+ public static DataServiceQuery Union(this DataServiceQuery source1, IEnumerable source2)
+ {
+ return new DataServiceQuery(source1.AsQueryable().Union(source2).Expression, new DataServiceQueryProvider(source1.Context));
+ }
+
+ ///
+ /// Filters a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.
+ ///
+ /// The type of the elements of .
+ /// A to filter.
+ ///
+ /// A function to test each element for a condition; the second parameter of the function represents the index of the element in the source sequence.
+ ///
+ ///
+ /// A that contains elements from the input sequence that satisfy the condition specified by
+ /// .
+ ///
+ /// Thrown if or is
+ public static DataServiceQuery Where(this DataServiceQuery source, Expression> predicate)
+ {
+ return new DataServiceQuery