1 //---------------------------------------------------------------------
2 // <copyright file="DbExpressionBuilder.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
10 namespace System
.Data
.Common
.CommandTrees
.ExpressionBuilder
13 using System
.Collections
.Generic
;
14 using System
.Data
.Common
;
15 using System
.Data
.Common
.CommandTrees
.ExpressionBuilder
.Internal
;
16 using System
.Data
.Common
.CommandTrees
.Internal
;
17 using System
.Data
.Common
.Utils
;
18 using System
.Data
.Entity
;
19 using System
.Data
.Metadata
.Edm
;
20 using System
.Diagnostics
;
21 using System
.Globalization
;
23 using System
.Reflection
;
24 using System
.Runtime
.CompilerServices
;
27 /// Provides an API to construct <see cref="DbExpression"/>s and allows that API to be accessed as extension methods on the expression type itself.
29 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId
= "Db")]
30 public static class DbExpressionBuilder
32 #region Private Implementation
34 private static readonly AliasGenerator _bindingAliases
= new AliasGenerator("Var_", 0);
36 private static readonly DbNullExpression _binaryNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Binary
));
37 private static readonly DbNullExpression _boolNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Boolean
));
38 private static readonly DbNullExpression _byteNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Byte
));
39 private static readonly DbNullExpression _dateTimeNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.DateTime
));
40 private static readonly DbNullExpression _dateTimeOffsetNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.DateTimeOffset
));
41 private static readonly DbNullExpression _decimalNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Decimal
));
42 private static readonly DbNullExpression _doubleNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Double
));
43 private static readonly DbNullExpression _geographyNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Geography
));
44 private static readonly DbNullExpression _geometryNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Geometry
));
45 private static readonly DbNullExpression _guidNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Guid
));
46 private static readonly DbNullExpression _int16Null
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Int16
));
47 private static readonly DbNullExpression _int32Null
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Int32
));
48 private static readonly DbNullExpression _int64Null
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Int64
));
49 private static readonly DbNullExpression _sbyteNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.SByte
));
50 private static readonly DbNullExpression _singleNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Single
));
51 private static readonly DbNullExpression _stringNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.String
));
52 private static readonly DbNullExpression _timeNull
= Null(EdmProviderManifest
.Instance
.GetCanonicalModelTypeUsage(PrimitiveTypeKind
.Time
));
54 private static readonly DbConstantExpression _boolTrue
= Constant(true);
55 private static readonly DbConstantExpression _boolFalse
= Constant(false);
59 #region Helpers (not strictly Command Tree API)
61 public static KeyValuePair
<string, DbExpression
> As(this DbExpression
value, string alias)
63 return new KeyValuePair
<string, DbExpression
>(alias, value);
66 public static KeyValuePair
<string, DbAggregate
> As(this DbAggregate
value, string alias)
68 return new KeyValuePair
<string, DbAggregate
>(alias, value);
73 #region Bindings - Expression and Group
76 /// Creates a new <see cref="DbExpressionBinding"/> that uses a generated variable name to bind the given expression
78 /// <param name="input">The expression to bind</param>
79 /// <returns>A new expression binding with the specified expression and a generated variable name</returns>
80 /// <exception cref="ArgumentNullException"><paramref name="input"/> is null</exception>
81 /// <exception cref="ArgumentException"><paramref name="input"/> does not have a collection result type</exception>
82 public static DbExpressionBinding
Bind(this DbExpression input
)
84 return DbExpressionBuilder
.BindAs(input
, _bindingAliases
.Next());
88 /// Creates a new <see cref="DbExpressionBinding"/> that uses the specified variable name to bind the given expression
90 /// <param name="input">The expression to bind</param>
91 /// <param name="varName">The variable name that should be used for the binding</param>
92 /// <returns>A new expression binding with the specified expression and variable name</returns>
93 /// <exception cref="ArgumentNullException"><paramref name="input"/> or <paramref name="varName"/> is null</exception>
94 /// <exception cref="ArgumentException"><paramref name="input"/> does not have a collection result type</exception>
95 public static DbExpressionBinding
BindAs(this DbExpression input
, string varName
)
97 TypeUsage elementType
= ArgumentValidation
.ValidateBindAs(input
, varName
);
98 DbVariableReferenceExpression inputRef
= new DbVariableReferenceExpression(elementType
, varName
);
99 return new DbExpressionBinding(input
, inputRef
);
103 /// Creates a new group expression binding that uses generated variable and group variable names to bind the given expression
105 /// <param name="input">The expression to bind</param>
106 /// <returns>A new group expression binding with the specified expression and a generated variable name and group variable name</returns>
107 /// <exception cref="ArgumentNullException"><paramref name="input"/> is null</exception>
108 /// <exception cref="ArgumentException"><paramref name="input"/> does not have a collection result type</exception>
109 public static DbGroupExpressionBinding
GroupBind(this DbExpression input
)
111 string alias = _bindingAliases
.Next();
112 return DbExpressionBuilder
.GroupBindAs(input
, alias, string.Format(CultureInfo
.InvariantCulture
, "Group{0}", alias));
116 /// Creates a new <see cref="DbGroupExpressionBinding"/> that uses the specified variable name and group variable names to bind the given expression
118 /// <param name="input">The expression to bind</param>
119 /// <param name="varName">The variable name that should be used for the binding</param>
120 /// <param name="groupVarName">The variable name that should be used to refer to the group when the new group expression binding is used in a group-by expression</param>
121 /// <returns>A new group expression binding with the specified expression, variable name and group variable name</returns>
122 /// <exception cref="ArgumentNullException"><paramref name="input"/>, <paramref name="varName"/> or <paramref name="groupVarName"/> is null</exception>
123 /// <exception cref="ArgumentException"><paramref name="input"/> does not have a collection result type</exception>
124 public static DbGroupExpressionBinding
GroupBindAs(this DbExpression input
, string varName
, string groupVarName
)
126 TypeUsage elementType
= ArgumentValidation
.ValidateGroupBindAs(input
, varName
, groupVarName
);
127 DbVariableReferenceExpression inputRef
= new DbVariableReferenceExpression(elementType
, varName
);
128 DbVariableReferenceExpression groupRef
= new DbVariableReferenceExpression(elementType
, groupVarName
);
129 return new DbGroupExpressionBinding(input
, inputRef
, groupRef
);
134 #region Aggregates and SortClauses are required only for Binding-based method support - replaced by OrderBy[Descending]/ThenBy[Descending] and Aggregate[Distinct] methods in new API
137 /// Creates a new <see cref="DbFunctionAggregate"/>.
139 /// <param name="function">The function that defines the aggregate operation.</param>
140 /// <param name="argument">The argument over which the aggregate function should be calculated.</param>
141 /// <returns>A new function aggregate with a reference to the given function and argument. The function aggregate's Distinct property will have the value false</returns>
142 /// <exception cref="ArgumentNullException"><paramref name="function"/> or <paramref name="argument"/> is null</exception>
143 /// <exception cref="ArgumentException">
144 /// <paramref name="function"/> is not an aggregate function or has more than one argument, or
145 /// the result type of <paramref name="argument"/> is not equal or promotable to
146 /// the parameter type of <paramref name="function"/>
148 public static DbFunctionAggregate
Aggregate(this EdmFunction function
, DbExpression argument
)
150 return CreateFunctionAggregate(function
, argument
, false);
154 /// Creates a new <see cref="DbFunctionAggregate"/> that is applied in a distinct fashion.
156 /// <param name="function">The function that defines the aggregate operation.</param>
157 /// <param name="argument">The argument over which the aggregate function should be calculated.</param>
158 /// <returns>A new function aggregate with a reference to the given function and argument. The function aggregate's Distinct property will have the value true</returns>
159 /// <exception cref="ArgumentNullException"><paramref name="function"/> or <paramref name="argument"/> is null</exception>
160 /// <exception cref="ArgumentException">
161 /// <paramref name="function"/> is not an aggregate function or has more than one argument, or
162 /// the result type of <paramref name="argument"/> is not equal or promotable to
163 /// the parameter type of <paramref name="function"/>
165 public static DbFunctionAggregate
AggregateDistinct(this EdmFunction function
, DbExpression argument
)
167 return CreateFunctionAggregate(function
, argument
, true);
170 private static DbFunctionAggregate
CreateFunctionAggregate(EdmFunction function
, DbExpression argument
, bool isDistinct
)
172 EntityUtil
.CheckArgumentNull(argument
, "argument");
173 DbExpressionList funcArgs
= ArgumentValidation
.ValidateFunctionAggregate(function
, new[] { argument }
);
174 TypeUsage resultType
= function
.ReturnParameter
.TypeUsage
;
175 return new DbFunctionAggregate(resultType
, funcArgs
, function
, isDistinct
);
179 /// Creates a new <see cref="DbGroupAggregate"/> over the specified argument
181 /// <param name="argument">The argument over which to perform the nest operation</param>
182 /// <returns>A new group aggregate representing the elements of the group referenced by the given argument.</returns>
183 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
184 /*ENABLE_ELEMENT_SELECTOR(*/internal/*)*/ static DbGroupAggregate
GroupAggregate(DbExpression argument
)
186 DbExpressionList arguments
= ArgumentValidation
.ValidateGroupAggregate(argument
);
187 TypeUsage resultType
= TypeHelpers
.CreateCollectionTypeUsage(argument
.ResultType
);
188 return new DbGroupAggregate(resultType
, arguments
);
192 /// Creates a <see cref="DbLambda"/> with the specified inline Lambda function implementation and formal parameters.
194 /// <param name="body">An expression that defines the logic of the Lambda function</param>
195 /// <param name="variables">
196 /// A <see cref="DbVariableReferenceExpression"/> collection that represents the formal parameters to the Lambda function.
197 /// These variables are valid for use in the <paramref name="body"/> expression.
199 /// <returns>A new DbLambda that describes an inline Lambda function with the specified body and formal parameters</returns>
200 /// <exception cref="ArgumentNullException">
201 /// <paramref name="variables"/> is null or contains null, or <paramref name="body"/> is null
203 /// <exception cref="ArgumentException">
204 /// <paramref name="variables"/> contains more than one element with the same variable name.
206 public static DbLambda
Lambda(DbExpression body
, IEnumerable
<DbVariableReferenceExpression
> variables
)
208 return CreateLambda(body
, variables
);
212 /// Creates a <see cref="DbLambda"/> with the specified inline Lambda function implementation and formal parameters.
214 /// <param name="body">An expression that defines the logic of the Lambda function</param>
215 /// <param name="variables">
216 /// A <see cref="DbVariableReferenceExpression"/> collection that represents the formal parameters to the Lambda function.
217 /// These variables are valid for use in the <paramref name="body"/> expression.
219 /// <returns>A new DbLambda that describes an inline Lambda function with the specified body and formal parameters</returns>
220 /// <exception cref="ArgumentNullException">
221 /// <paramref name="variables"/> is null or contains null, or <paramref name="body"/> is null
223 /// <exception cref="ArgumentException">
224 /// <paramref name="variables"/> contains more than one element with the same variable name.
226 public static DbLambda
Lambda(DbExpression body
, params DbVariableReferenceExpression
[] variables
)
228 return CreateLambda(body
, variables
);
231 private static DbLambda
CreateLambda(DbExpression body
, IEnumerable
<DbVariableReferenceExpression
> variables
)
233 var validVars
= ArgumentValidation
.ValidateLambda(variables
, body
);
234 return new DbLambda(validVars
, body
);
238 /// Creates a new <see cref="DbSortClause"/> with an ascending sort order and default collation
240 /// <param name="key">The expression that defines the sort key</param>
241 /// <returns>A new sort clause with the given sort key and ascending sort order</returns>
242 /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
243 /// <exception cref="ArgumentException"><paramref name="key"/> does not have an order-comparable result type</exception>
244 public static DbSortClause
ToSortClause(this DbExpression key
)
246 ArgumentValidation
.ValidateSortClause(key
);
247 return new DbSortClause(key
, true, String
.Empty
);
251 /// Creates a new <see cref="DbSortClause"/> with a descending sort order and default collation
253 /// <param name="key">The expression that defines the sort key</param>
254 /// <returns>A new sort clause with the given sort key and descending sort order</returns>
255 /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
256 /// <exception cref="ArgumentException"><paramref name="key"/> does not have an order-comparable result type</exception>
257 public static DbSortClause
ToSortClauseDescending(this DbExpression key
)
259 ArgumentValidation
.ValidateSortClause(key
);
260 return new DbSortClause(key
, false, String
.Empty
);
264 /// Creates a new <see cref="DbSortClause"/> with an ascending sort order and the specified collation
266 /// <param name="key">The expression that defines the sort key</param>
267 /// <param name="collation">The collation to sort under</param>
268 /// <returns>A new sort clause with the given sort key and collation, and ascending sort order</returns>
269 /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
270 /// <exception cref="ArgumentOutOfRangeException"><paramref name="collation"/> is empty or contains only space characters</exception>
271 /// <exception cref="ArgumentException"><paramref name="key"/> does not have an order-comparable result type</exception>
272 public static DbSortClause
ToSortClause(this DbExpression key
, string collation
)
274 ArgumentValidation
.ValidateSortClause(key
, collation
);
275 return new DbSortClause(key
, true, collation
);
279 /// Creates a new <see cref="DbSortClause"/> with a descending sort order and the specified collation
281 /// <param name="key">The expression that defines the sort key</param>
282 /// <param name="collation">The collation to sort under</param>
283 /// <returns>A new sort clause with the given sort key and collation, and descending sort order</returns>
284 /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
285 /// <exception cref="ArgumentOutOfRangeException"><paramref name="collation"/> is empty or contains only space characters</exception>
286 /// <exception cref="ArgumentException"><paramref name="key"/> does not have an order-comparable result type</exception>
287 public static DbSortClause
ToSortClauseDescending(this DbExpression key
, string collation
)
289 ArgumentValidation
.ValidateSortClause(key
, collation
);
290 return new DbSortClause(key
, false, collation
);
295 #region Binding-based methods: All, Any, Cross|OuterApply, Cross|FullOuter|Inner|LeftOuterJoin, Filter, GroupBy, Project, Skip, Sort
298 /// Creates a new <see cref="DbQuantifierExpression"/> that determines whether the given predicate holds for all elements of the input set.
300 /// <param name="input">An expression binding that specifies the input set.</param>
301 /// <param name="predicate">An expression representing a predicate to evaluate for each member of the input set.</param>
302 /// <returns>A new DbQuantifierExpression that represents the All operation.</returns>
303 /// <exception cref="ArgumentNullException"><paramref name="input"/> or <paramref name="predicate"/> is null</exception>
304 /// <exception cref="ArgumentException">
305 /// <paramref name="predicate"/> does not have a Boolean result type.
307 public static DbQuantifierExpression
All(this DbExpressionBinding input
, DbExpression predicate
)
309 TypeUsage booleanResultType
= ArgumentValidation
.ValidateQuantifier(input
, predicate
);
310 return new DbQuantifierExpression(DbExpressionKind
.All
, booleanResultType
, input
, predicate
);
314 /// Creates a new <see cref="DbQuantifierExpression"/> that determines whether the given predicate holds for any element of the input set.
316 /// <param name="input">An expression binding that specifies the input set.</param>
317 /// <param name="predicate">An expression representing a predicate to evaluate for each member of the input set.</param>
318 /// <returns>A new DbQuantifierExpression that represents the Any operation.</returns>
319 /// <exception cref="ArgumentNullException"><paramref name="input"/> or <paramref name="predicate"/> is null</exception>
320 /// <exception cref="ArgumentException">
321 /// <paramref name="predicate"/> does not have a Boolean result type.
323 public static DbQuantifierExpression
Any(this DbExpressionBinding input
, DbExpression predicate
)
325 TypeUsage booleanResultType
= ArgumentValidation
.ValidateQuantifier(input
, predicate
);
326 return new DbQuantifierExpression(DbExpressionKind
.Any
, booleanResultType
, input
, predicate
);
330 /// Creates a new <see cref="DbApplyExpression"/> that evaluates the given <paramref name="apply"/> expression once for each element of a given input set,
331 /// producing a collection of rows with corresponding input and apply columns. Rows for which <paramref name="apply"/> evaluates to an empty set are not included.
333 /// <param name="input">An <see cref="DbExpressionBinding"/> that specifies the input set.</param>
334 /// <param name="apply">An <see cref="DbExpressionBinding"/> that specifies logic to evaluate once for each member of the input set.</param>
335 /// <returns>An new DbApplyExpression with the specified input and apply bindings and an <see cref="DbExpressionKind"/> of CrossApply.</returns>
336 /// <exception cref="ArgumentNullException"><paramref name="input"/> or <paramref name="apply"/> is null</exception>
337 public static DbApplyExpression
CrossApply(this DbExpressionBinding input
, DbExpressionBinding apply
)
339 TypeUsage resultType
= ArgumentValidation
.ValidateApply(input
, apply
);
340 return new DbApplyExpression(DbExpressionKind
.CrossApply
, resultType
, input
, apply
);
344 /// Creates a new <see cref="DbApplyExpression"/> that evaluates the given <paramref name="apply"/> expression once for each element of a given input set,
345 /// producing a collection of rows with corresponding input and apply columns. Rows for which <paramref name="apply"/> evaluates to an empty set have an apply column value of <code>null</code>.
347 /// <param name="input">An <see cref="DbExpressionBinding"/> that specifies the input set.</param>
348 /// <param name="apply">An <see cref="DbExpressionBinding"/> that specifies logic to evaluate once for each member of the input set.</param>
349 /// <returns>An new DbApplyExpression with the specified input and apply bindings and an <see cref="DbExpressionKind"/> of OuterApply.</returns>
350 /// <exception cref="ArgumentNullException"><paramref name="input"/> or <paramref name="apply"/> is null</exception>
351 public static DbApplyExpression
OuterApply(this DbExpressionBinding input
, DbExpressionBinding apply
)
353 TypeUsage resultType
= ArgumentValidation
.ValidateApply(input
, apply
);
354 return new DbApplyExpression(DbExpressionKind
.OuterApply
, resultType
, input
, apply
);
358 /// Creates a new <see cref="DbCrossJoinExpression"/> that unconditionally joins the sets specified by the list of input expression bindings.
360 /// <param name="inputs">A list of expression bindings that specifies the input sets.</param>
361 /// <returns>A new DbCrossJoinExpression, with an <see cref="DbExpressionKind"/> of CrossJoin, that represents the unconditional join of the input sets.</returns>
362 /// <exception cref="ArgumentNullException"><paramref name="inputs"/> is null or contains null</exception>
363 /// <exception cref="ArgumentException">
364 /// <paramref name="inputs"/> contains fewer than 2 expression bindings.
366 public static DbCrossJoinExpression
CrossJoin(IEnumerable
<DbExpressionBinding
> inputs
)
368 TypeUsage resultType
;
369 System
.Collections
.ObjectModel
.ReadOnlyCollection
<DbExpressionBinding
> validInputs
= ArgumentValidation
.ValidateCrossJoin(inputs
, out resultType
);
370 return new DbCrossJoinExpression(resultType
, validInputs
);
374 /// Creates a new <see cref="DbJoinExpression"/> that joins the sets specified by the left and right
375 /// expression bindings, on the specified join condition, using InnerJoin as the <see cref="DbExpressionKind"/>.
377 /// <param name="left">An <see cref="DbExpressionBinding"/> that specifies the left set argument.</param>
378 /// <param name="right">An <see cref="DbExpressionBinding"/> that specifies the right set argument.</param>
379 /// <param name="joinCondition">An expression that specifies the condition on which to join.</param>
381 /// A new DbJoinExpression, with an <see cref="DbExpressionKind"/> of InnerJoin, that represents the inner join operation applied to the left and right
382 /// input sets under the given join condition.
384 /// <exception cref="ArgumentNullException">
385 /// <paramref name="left"/>, <paramref name="right"/> or <paramref name="joinCondition"/> is null.
387 /// <exception cref="ArgumentException">
388 /// <paramref name="joinCondition"/> does not have a Boolean result type.
390 public static DbJoinExpression
InnerJoin(this DbExpressionBinding left
, DbExpressionBinding right
, DbExpression joinCondition
)
392 TypeUsage resultType
= ArgumentValidation
.ValidateJoin(left
, right
, joinCondition
);
393 return new DbJoinExpression(DbExpressionKind
.InnerJoin
, resultType
, left
, right
, joinCondition
);
397 /// Creates a new <see cref="DbJoinExpression"/> that joins the sets specified by the left and right
398 /// expression bindings, on the specified join condition, using LeftOuterJoin as the <see cref="DbExpressionKind"/>.
400 /// <param name="left">An <see cref="DbExpressionBinding"/> that specifies the left set argument.</param>
401 /// <param name="right">An <see cref="DbExpressionBinding"/> that specifies the right set argument.</param>
402 /// <param name="joinCondition">An expression that specifies the condition on which to join.</param>
404 /// A new DbJoinExpression, with an <see cref="DbExpressionKind"/> of LeftOuterJoin, that represents the left outer join operation applied to the left and right
405 /// input sets under the given join condition.
407 /// <exception cref="ArgumentNullException">
408 /// <paramref name="left"/>, <paramref name="right"/> or <paramref name="joinCondition"/> is null.
410 /// <exception cref="ArgumentException">
411 /// <paramref name="joinCondition"/> does not have a Boolean result type.
413 public static DbJoinExpression
LeftOuterJoin(this DbExpressionBinding left
, DbExpressionBinding right
, DbExpression joinCondition
)
415 TypeUsage resultType
= ArgumentValidation
.ValidateJoin(left
, right
, joinCondition
);
416 return new DbJoinExpression(DbExpressionKind
.LeftOuterJoin
, resultType
, left
, right
, joinCondition
);
420 /// Creates a new <see cref="DbJoinExpression"/> that joins the sets specified by the left and right
421 /// expression bindings, on the specified join condition, using FullOuterJoin as the <see cref="DbExpressionKind"/>.
423 /// <param name="left">An <see cref="DbExpressionBinding"/> that specifies the left set argument.</param>
424 /// <param name="right">An <see cref="DbExpressionBinding"/> that specifies the right set argument.</param>
425 /// <param name="joinCondition">An expression that specifies the condition on which to join.</param>
427 /// A new DbJoinExpression, with an <see cref="DbExpressionKind"/> of FullOuterJoin, that represents the full outer join operation applied to the left and right
428 /// input sets under the given join condition.
430 /// <exception cref="ArgumentNullException">
431 /// <paramref name="left"/>, <paramref name="right"/> or <paramref name="joinCondition"/> is null.
433 /// <exception cref="ArgumentException">
434 /// <paramref name="joinCondition"/> does not have a Boolean result type.
436 public static DbJoinExpression
FullOuterJoin(this DbExpressionBinding left
, DbExpressionBinding right
, DbExpression joinCondition
)
438 TypeUsage resultType
= ArgumentValidation
.ValidateJoin(left
, right
, joinCondition
);
439 return new DbJoinExpression(DbExpressionKind
.FullOuterJoin
, resultType
, left
, right
, joinCondition
);
443 /// Creates a new <see cref="DbFilterExpression"/> that filters the elements in the given input set using the specified predicate.
445 /// <param name="input">An expression binding that specifies the input set.</param>
446 /// <param name="predicate">An expression representing a predicate to evaluate for each member of the input set.</param>
447 /// <returns>A new DbFilterExpression that produces the filtered set.</returns>
448 /// <exception cref="ArgumentNullException"><paramref name="input"/> or <paramref name="predicate"/> is null</exception>
449 /// <exception cref="ArgumentException">
450 /// <paramref name="predicate"/> does not have a Boolean result type.
452 public static DbFilterExpression
Filter(this DbExpressionBinding input
, DbExpression predicate
)
454 TypeUsage resultType
= ArgumentValidation
.ValidateFilter(input
, predicate
);
455 return new DbFilterExpression(resultType
, input
, predicate
);
459 /// Creates a new <see cref="DbGroupByExpression"/> that groups the elements of the input set according to the specified group keys and applies the given aggregates.
461 /// <param name="input">A <see cref="DbGroupExpressionBinding"/> that specifies the input set.</param>
462 /// <param name="keys">A list of string-expression pairs that define the grouping columns.</param>
463 /// <param name="aggregates">A list of expressions that specify aggregates to apply.</param>
464 /// <returns>A new DbGroupByExpression with the specified input set, grouping keys and aggregates.</returns>
465 /// <exception cref="ArgumentNullException">
466 /// <paramref name="input"/>, <paramref name="keys"/> or <paramref name="aggregates"/> is null,
467 /// <paramref name="keys"/> contains a null key column name or expression, or
468 /// <paramref name="aggregates"/> contains a null aggregate column name or aggregate.
470 /// <exception cref="ArgumentException">
471 /// Both <paramref name="keys"/> and <paramref name="aggregates"/> are empty,
472 /// or an invalid or duplicate column name was specified.
475 /// DbGroupByExpression allows either the list of keys or the list of aggregates to be empty, but not both.
477 public static DbGroupByExpression
GroupBy(this DbGroupExpressionBinding input
, IEnumerable
<KeyValuePair
<string, DbExpression
>> keys
, IEnumerable
<KeyValuePair
<string, DbAggregate
>> aggregates
)
479 DbExpressionList validKeys
;
480 System
.Collections
.ObjectModel
.ReadOnlyCollection
<DbAggregate
> validAggregates
;
481 TypeUsage resultType
= ArgumentValidation
.ValidateGroupBy(input
, keys
, aggregates
, out validKeys
, out validAggregates
);
482 return new DbGroupByExpression(resultType
, input
, validKeys
, validAggregates
);
486 /// Creates a new <see cref="DbProjectExpression"/> that projects the specified expression over the given input set.
488 /// <param name="input">An expression binding that specifies the input set.</param>
489 /// <param name="projection">An expression to project over the set.</param>
490 /// <returns>A new DbProjectExpression that represents the projection operation.</returns>
491 /// <exception cref="ArgumentNullException"><paramref name="input"/> or <paramref name="projection"/> is null</exception>
492 public static DbProjectExpression
Project(this DbExpressionBinding input
, DbExpression projection
)
494 TypeUsage resultType
= ArgumentValidation
.ValidateProject(input
, projection
);
495 return new DbProjectExpression(resultType
, input
, projection
);
499 /// Creates a new <see cref="DbSkipExpression"/> that sorts the given input set by the given sort specifications before skipping the specified number of elements.
501 /// <param name="input">An expression binding that specifies the input set.</param>
502 /// <param name="sortOrder">A list of sort specifications that determine how the elements of the input set should be sorted.</param>
503 /// <param name="count">An expression the specifies how many elements of the ordered set to skip.</param>
504 /// <returns>A new DbSkipExpression that represents the skip operation.</returns>
505 /// <exception cref="ArgumentNullException">
506 /// <paramref name="input"/>, <paramref name="sortOrder"/> or <paramref name="count"/> is null,
507 /// or <paramref name="sortOrder"/> contains null.
509 /// <exception cref="ArgumentException">
510 /// <paramref name="sortOrder"/> is empty,
511 /// or <paramref name="count"/> is not <see cref="DbConstantExpression"/> or <see cref="DbParameterReferenceExpression"/> or has a
512 /// result type that is not equal or promotable to a 64-bit integer type.
514 public static DbSkipExpression
Skip(this DbExpressionBinding input
, IEnumerable
<DbSortClause
> sortOrder
, DbExpression count
)
516 System
.Collections
.ObjectModel
.ReadOnlyCollection
<DbSortClause
> validSortOrder
= ArgumentValidation
.ValidateSkip(input
, sortOrder
, count
);
517 return new DbSkipExpression(input
.Expression
.ResultType
, input
, validSortOrder
, count
);
521 /// Creates a new <see cref="DbSortExpression"/> that sorts the given input set by the specified sort specifications.
523 /// <param name="input">An expression binding that specifies the input set.</param>
524 /// <param name="sortOrder">A list of sort specifications that determine how the elements of the input set should be sorted.</param>
525 /// <returns>A new DbSortExpression that represents the sort operation.</returns>
526 /// <exception cref="ArgumentNullException">
527 /// <paramref name="input"/> or <paramref name="sortOrder"/> is null,
528 /// or <paramref name="sortOrder"/> contains null.
530 /// <exception cref="ArgumentException">
531 /// <paramref name="sortOrder"/> is empty.
533 public static DbSortExpression
Sort(this DbExpressionBinding input
, IEnumerable
<DbSortClause
> sortOrder
)
535 System
.Collections
.ObjectModel
.ReadOnlyCollection
<DbSortClause
> validSortOrder
= ArgumentValidation
.ValidateSort(input
, sortOrder
);
536 return new DbSortExpression(input
.Expression
.ResultType
, input
, validSortOrder
);
541 #region Leaf Expressions - Null, Constant, Parameter, Scan
543 #if DBEXPRESSIONBUILDER_NULLCONSTANTS
545 public static DbNullExpression NullBinary { get { return _binaryNull; }
}
547 public static DbNullExpression NullBoolean { get { return _boolNull; }
}
549 public static DbNullExpression NullByte { get { return _byteNull; }
}
551 public static DbNullExpression NullDateTime { get { return _dateTimeNull; }
}
553 public static DbNullExpression NullDateTimeOffset { get { return _dateTimeOffsetNull; }
}
555 public static DbNullExpression NullDecimal { get { return _decimalNull; }
}
557 public static DbNullExpression NullDouble { get { return _doubleNull; }
}
559 public static DbNullExpression NullGuid { get { return _guidNull; }
}
561 public static DbNullExpression NullInt16 { get { return _int16Null; }
}
563 public static DbNullExpression NullInt32 { get { return _int32Null; }
}
565 public static DbNullExpression NullInt64 { get { return _int64Null; }
}
567 public static DbNullExpression NullSByte { get { return _sbyteNull; }
}
569 public static DbNullExpression NullSingle { get { return _singleNull; }
}
571 public static DbNullExpression NullString { get { return _stringNull; }
}
573 public static DbNullExpression NullTime { get { return _timeNull; }
}
577 /// Creates a new <see cref="DbNullExpression"/>, which represents a typed null value.
579 /// <param name="nullType">The type of the null value.</param>
580 /// <returns>An instance of DbNullExpression</returns>
581 /// <exception cref="ArgumentNullException"><paramref name="nullType"/> is null</exception>
582 public static DbNullExpression
Null(this TypeUsage nullType
)
584 ArgumentValidation
.ValidateNull(nullType
);
585 return new DbNullExpression(nullType
);
589 /// Creates a <see cref="DbConstantExpression"/> with the Boolean value <code>true</code>.
591 /// <returns>A DbConstantExpression with the Boolean value true.</returns>
592 public static DbConstantExpression True { get { return _boolTrue; }
}
595 /// Creates a <see cref="DbConstantExpression"/> with the Boolean value <code>false</code>.
597 /// <returns>A DbConstantExpression with the Boolean value false.</returns>
598 public static DbConstantExpression False { get { return _boolFalse; }
}
601 /// Creates a new <see cref="DbConstantExpression"/> with the given constant value.
603 /// <param name="value">The constant value to represent.</param>
604 /// <returns>A new DbConstantExpression with the given value.</returns>
605 /// <exception cref="ArgumentNullException"><paramref name="value"/> is null</exception>
606 /// <exception cref="ArgumentException"><paramref name="value"/> is not an instance of a valid constant type</exception>
607 public static DbConstantExpression
Constant(object value)
609 TypeUsage constantType
= ArgumentValidation
.ValidateConstant(value);
610 return new DbConstantExpression(constantType
, value);
614 /// Creates a new <see cref="DbConstantExpression"/> of the specified primitive type with the given constant value.
616 /// <param name="constantType">The type of the constant value.</param>
617 /// <param name="value">The constant value to represent.</param>
618 /// <returns>A new DbConstantExpression with the given value and a result type of <paramref name="constantType"/>.</returns>
619 /// <exception cref="ArgumentNullException"><paramref name="value"/> or <paramref name="constantType"/> is null</exception>
620 /// <exception cref="ArgumentException">
621 /// <paramref name="value"/> is not an instance of a valid constant type,
622 /// <paramref name="constantType"/> does not represent a primitive type, or
623 /// <paramref name="value"/> is of a different primitive type than that represented by <paramref name="constantType"/>
625 public static DbConstantExpression
Constant(this TypeUsage constantType
, object value)
627 ArgumentValidation
.ValidateConstant(constantType
, value);
628 return new DbConstantExpression(constantType
, value);
632 /// Creates a new <see cref="DbParameterReferenceExpression"/> that references a parameter with the specified name and type.
634 /// <param name="type">The type of the referenced parameter</param>
635 /// <param name="name">The name of the referenced parameter</param>
637 /// A DbParameterReferenceExpression that represents a reference to a parameter with the specified name and type;
638 /// the result type of the expression will be the same as <paramref name="type"/>.
640 public static DbParameterReferenceExpression
Parameter(this TypeUsage type
, string name
)
642 ArgumentValidation
.ValidateParameter(type
, name
);
643 return new DbParameterReferenceExpression(type
, name
);
647 /// Creates a new <see cref="DbVariableReferenceExpression"/> that references a variable with the specified name and type.
649 /// <param name="type">The type of the referenced variable</param>
650 /// <param name="name">The name of the referenced variable</param>
652 /// A DbVariableReferenceExpression that represents a reference to a variable with the specified name and type;
653 /// the result type of the expression will be the same as <paramref name="type"/>.
655 public static DbVariableReferenceExpression
Variable(this TypeUsage type
, string name
)
657 ArgumentValidation
.ValidateVariable(type
, name
);
658 return new DbVariableReferenceExpression(type
, name
);
662 /// Creates a new <see cref="DbScanExpression"/> that references the specified entity or relationship set.
664 /// <param name="targetSet">Metadata for the entity or relationship set to reference.</param>
665 /// <returns>A new DbScanExpression based on the specified entity or relationship set.</returns>
666 /// <exception cref="ArgumentNullException"><paramref name="targetSet"/> is null</exception>
667 public static DbScanExpression
Scan(this EntitySetBase targetSet
)
669 TypeUsage resultType
= ArgumentValidation
.ValidateScan(targetSet
);
670 return new DbScanExpression(resultType
, targetSet
);
675 #region Boolean Operators - And, Or, Not
678 /// Creates an <see cref="DbAndExpression"/> that performs the logical And of the left and right arguments.
680 /// <param name="left">A Boolean expression that specifies the left argument.</param>
681 /// <param name="right">A Boolean expression that specifies the right argument.</param>
682 /// <returns>A new DbAndExpression with the specified arguments.</returns>
683 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
684 /// <exception cref="ArgumentException">
685 /// <paramref name="left"/> or <paramref name="right"/> does not have a Boolean result type.
687 public static DbAndExpression
And(this DbExpression left
, DbExpression right
)
689 TypeUsage resultType
= ArgumentValidation
.ValidateAnd(left
, right
);
690 return new DbAndExpression(resultType
, left
, right
);
694 /// Creates an <see cref="DbOrExpression"/> that performs the logical Or of the left and right arguments.
696 /// <param name="left">A Boolean expression that specifies the left argument.</param>
697 /// <param name="right">A Boolean expression that specifies the right argument.</param>
698 /// <returns>A new DbOrExpression with the specified arguments.</returns>
699 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
700 /// <exception cref="ArgumentException">
701 /// <paramref name="left"/> or <paramref name="right"/> does not have a Boolean result type.
703 public static DbOrExpression
Or(this DbExpression left
, DbExpression right
)
705 TypeUsage resultType
= ArgumentValidation
.ValidateOr(left
, right
);
706 return new DbOrExpression(resultType
, left
, right
);
710 /// Creates a <see cref="DbNotExpression"/> that performs the logical negation of the given argument.
712 /// <param name="argument">A Boolean expression that specifies the argument.</param>
713 /// <returns>A new DbNotExpression with the specified argument.</returns>
714 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
715 /// <exception cref="ArgumentException">
716 /// <paramref name="argument"/> does not have a Boolean result type.
718 public static DbNotExpression
Not(this DbExpression argument
)
720 TypeUsage resultType
= ArgumentValidation
.ValidateNot(argument
);
721 return new DbNotExpression(resultType
, argument
);
726 #region Arithmetic Operators - Divide, Minus, Modulo, Multiply, Plus, UnaryMinus
728 private static DbArithmeticExpression
CreateArithmetic(DbExpressionKind kind
, DbExpression left
, DbExpression right
)
730 TypeUsage numericResultType
;
731 DbExpressionList arguments
= ArgumentValidation
.ValidateArithmetic(left
, right
, out numericResultType
);
732 return new DbArithmeticExpression(kind
, numericResultType
, arguments
);
736 /// Creates a new <see cref="DbArithmeticExpression"/> that divides the left argument by the right argument.
738 /// <param name="left">An expression that specifies the left argument.</param>
739 /// <param name="right">An expression that specifies the right argument.</param>
740 /// <returns>A new DbArithmeticExpression representing the division operation.</returns>
741 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
742 /// <exception cref="ArgumentException">
743 /// No common numeric result type exists between <paramref name="left"/> and <paramref name="right"/>.
745 public static DbArithmeticExpression
Divide(this DbExpression left
, DbExpression right
)
747 return CreateArithmetic(DbExpressionKind
.Divide
, left
, right
);
751 /// Creates a new <see cref="DbArithmeticExpression"/> that subtracts the right argument from the left argument.
753 /// <param name="left">An expression that specifies the left argument.</param>
754 /// <param name="right">An expression that specifies the right argument.</param>
755 /// <returns>A new DbArithmeticExpression representing the subtraction operation.</returns>
756 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
757 /// <exception cref="ArgumentException">
758 /// No common numeric result type exists between <paramref name="left"/> and <paramref name="right"/>.
760 public static DbArithmeticExpression
Minus(this DbExpression left
, DbExpression right
)
762 return CreateArithmetic(DbExpressionKind
.Minus
, left
, right
);
766 /// Creates a new <see cref="DbArithmeticExpression"/> that computes the remainder of the left argument divided by the right argument.
768 /// <param name="left">An expression that specifies the left argument.</param>
769 /// <param name="right">An expression that specifies the right argument.</param>
770 /// <returns>A new DbArithmeticExpression representing the modulo operation.</returns>
771 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
772 /// <exception cref="ArgumentException">
773 /// No common numeric result type exists between <paramref name="left"/> and <paramref name="right"/>.
775 public static DbArithmeticExpression
Modulo(this DbExpression left
, DbExpression right
)
777 return CreateArithmetic(DbExpressionKind
.Modulo
, left
, right
);
781 /// Creates a new <see cref="DbArithmeticExpression"/> that multiplies the left argument by the right argument.
783 /// <param name="left">An expression that specifies the left argument.</param>
784 /// <param name="right">An expression that specifies the right argument.</param>
785 /// <returns>A new DbArithmeticExpression representing the multiplication operation.</returns>
786 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
787 /// <exception cref="ArgumentException">
788 /// No common numeric result type exists between <paramref name="left"/> and <paramref name="right"/>.
790 public static DbArithmeticExpression
Multiply(this DbExpression left
, DbExpression right
)
792 return CreateArithmetic(DbExpressionKind
.Multiply
, left
, right
);
796 /// Creates a new <see cref="DbArithmeticExpression"/> that adds the left argument to the right argument.
798 /// <param name="left">An expression that specifies the left argument.</param>
799 /// <param name="right">An expression that specifies the right argument.</param>
800 /// <returns>A new DbArithmeticExpression representing the addition operation.</returns>
801 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
802 /// <exception cref="ArgumentException">
803 /// No common numeric result type exists between <paramref name="left"/> and <paramref name="right"/>.
805 public static DbArithmeticExpression
Plus(this DbExpression left
, DbExpression right
)
807 return CreateArithmetic(DbExpressionKind
.Plus
, left
, right
);
811 /// Creates a new <see cref="DbArithmeticExpression"/> that negates the value of the argument.
813 /// <param name="argument">An expression that specifies the argument.</param>
814 /// <returns>A new DbArithmeticExpression representing the negation operation.</returns>
815 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
816 /// <exception cref="ArgumentException">
817 /// No numeric result type exists for <paramref name="argument"/>.
819 public static DbArithmeticExpression
UnaryMinus(this DbExpression argument
)
821 TypeUsage resultType
;
822 DbExpressionList args
= ArgumentValidation
.ValidateArithmetic(argument
, out resultType
);
823 return new DbArithmeticExpression(DbExpressionKind
.UnaryMinus
, resultType
, args
);
827 /// Creates a new <see cref="DbArithmeticExpression"/> that negates the value of the argument.
829 /// <param name="argument">An expression that specifies the argument.</param>
830 /// <returns>A new DbArithmeticExpression representing the negation operation.</returns>
831 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
832 /// <exception cref="ArgumentException">
833 /// No numeric result type exists for <paramref name="argument"/>.
835 public static DbArithmeticExpression
Negate(this DbExpression argument
)
837 return DbExpressionBuilder
.UnaryMinus(argument
);
842 #region Comparison Operators - Equal, NotEqual, GreaterThan, LessThan, GreaterThanEqual, LessThanEqual, IsNull, Like
844 private static DbComparisonExpression
CreateComparison(DbExpressionKind kind
, DbExpression left
, DbExpression right
)
846 TypeUsage resultType
= ArgumentValidation
.ValidateComparison(kind
, left
, right
);
847 return new DbComparisonExpression(kind
, resultType
, left
, right
);
851 /// Creates a new <see cref="DbComparisonExpression"/> that compares the left and right arguments for equality.
853 /// <param name="left">An expression that specifies the left argument.</param>
854 /// <param name="right">An expression that specifies the right argument.</param>
855 /// <returns>A new DbComparisonExpression representing the equality comparison.</returns>
856 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
857 /// <exception cref="ArgumentException">
858 /// No common equality-comparable result type exists between <paramref name="left"/> and <paramref name="right"/>.
860 public static DbComparisonExpression
Equal(this DbExpression left
, DbExpression right
)
862 return DbExpressionBuilder
.CreateComparison(DbExpressionKind
.Equals
, left
, right
);
866 /// Creates a new <see cref="DbComparisonExpression"/> that compares the left and right arguments for inequality.
868 /// <param name="left">An expression that specifies the left argument.</param>
869 /// <param name="right">An expression that specifies the right argument.</param>
870 /// <returns>A new DbComparisonExpression representing the inequality comparison.</returns>
871 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
872 /// <exception cref="ArgumentException">
873 /// No common equality-comparable result type exists between <paramref name="left"/> and <paramref name="right"/>.
875 public static DbComparisonExpression
NotEqual(this DbExpression left
, DbExpression right
)
877 return DbExpressionBuilder
.CreateComparison(DbExpressionKind
.NotEquals
, left
, right
);
881 /// Creates a new <see cref="DbComparisonExpression"/> that determines whether the left argument is greater than the right argument.
883 /// <param name="left">An expression that specifies the left argument.</param>
884 /// <param name="right">An expression that specifies the right argument.</param>
885 /// <returns>A new DbComparisonExpression representing the greater-than comparison.</returns>
886 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
887 /// <exception cref="ArgumentException">
888 /// No common order-comparable result type exists between <paramref name="left"/> and <paramref name="right"/>.
890 public static DbComparisonExpression
GreaterThan(this DbExpression left
, DbExpression right
)
892 return DbExpressionBuilder
.CreateComparison(DbExpressionKind
.GreaterThan
, left
, right
);
896 /// Creates a new <see cref="DbComparisonExpression"/> that determines whether the left argument is less than the right argument.
898 /// <param name="left">An expression that specifies the left argument.</param>
899 /// <param name="right">An expression that specifies the right argument.</param>
900 /// <returns>A new DbComparisonExpression representing the less-than comparison.</returns>
901 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
902 /// <exception cref="ArgumentException">
903 /// No common order-comparable result type exists between <paramref name="left"/> and <paramref name="right"/>.
905 public static DbComparisonExpression
LessThan(this DbExpression left
, DbExpression right
)
907 return DbExpressionBuilder
.CreateComparison(DbExpressionKind
.LessThan
, left
, right
);
911 /// Creates a new <see cref="DbComparisonExpression"/> that determines whether the left argument is greater than or equal to the right argument.
913 /// <param name="left">An expression that specifies the left argument.</param>
914 /// <param name="right">An expression that specifies the right argument.</param>
915 /// <returns>A new DbComparisonExpression representing the greater-than-or-equal-to comparison.</returns>
916 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
917 /// <exception cref="ArgumentException">
918 /// No common result type that is both equality- and order-comparable exists between <paramref name="left"/> and <paramref name="right"/>.
920 public static DbComparisonExpression
GreaterThanOrEqual(this DbExpression left
, DbExpression right
)
922 return DbExpressionBuilder
.CreateComparison(DbExpressionKind
.GreaterThanOrEquals
, left
, right
);
926 /// Creates a new <see cref="DbComparisonExpression"/> that determines whether the left argument is less than or equal to the right argument.
928 /// <param name="left">An expression that specifies the left argument.</param>
929 /// <param name="right">An expression that specifies the right argument.</param>
930 /// <returns>A new DbComparisonExpression representing the less-than-or-equal-to comparison.</returns>
931 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
932 /// <exception cref="ArgumentException">
933 /// No common result type that is both equality- and order-comparable exists between <paramref name="left"/> and <paramref name="right"/>.
935 public static DbComparisonExpression
LessThanOrEqual(this DbExpression left
, DbExpression right
)
937 return DbExpressionBuilder
.CreateComparison(DbExpressionKind
.LessThanOrEquals
, left
, right
);
941 /// Creates a new <see cref="DbIsNullExpression"/> that determines whether the specified argument is null.
943 /// <param name="argument">An expression that specifies the argument.</param>
944 /// <returns>A new DbIsNullExpression with the specified argument.</returns>
945 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
946 /// <exception cref="ArgumentException"><paramref name="argument"/> has a collection result type.</exception>
947 public static DbIsNullExpression
IsNull(this DbExpression argument
)
949 TypeUsage resultType
= ArgumentValidation
.ValidateIsNull(argument
);
950 return new DbIsNullExpression(resultType
, argument
, false);
954 /// Creates a new <see cref="DbLikeExpression"/> that compares the specified input string to the given pattern.
956 /// <param name="argument">An expression that specifies the input string.</param>
957 /// <param name="pattern">An expression that specifies the pattern string.</param>
958 /// <returns>A new DbLikeExpression with the specified input, pattern and a null escape.</returns>
959 /// <exception cref="ArgumentNullException"><paramref name="argument"/> or <paramref name="pattern"/> is null</exception>
960 /// <exception cref="ArgumentException"><paramref name="argument"/> or <paramref name="pattern"/> does not have a string result type.</exception>
961 public static DbLikeExpression
Like(this DbExpression argument
, DbExpression pattern
)
963 TypeUsage resultType
= ArgumentValidation
.ValidateLike(argument
, pattern
);
964 DbExpression escape
= DbExpressionBuilder
.Null(pattern
.ResultType
);
965 return new DbLikeExpression(resultType
, argument
, pattern
, escape
);
969 /// Creates a new <see cref="DbLikeExpression"/> that compares the specified input string to the given pattern using the optional escape.
971 /// <param name="argument">An expression that specifies the input string.</param>
972 /// <param name="pattern">An expression that specifies the pattern string.</param>
973 /// <param name="escape">An optional expression that specifies the escape string.</param>
974 /// <returns>A new DbLikeExpression with the specified input, pattern and escape.</returns>
975 /// <exception cref="ArgumentNullException"><paramref name="argument"/>, <paramref name="pattern"/> or <paramref name="escape"/> is null</exception>
976 /// <exception cref="ArgumentException"><paramref name="argument"/>, <paramref name="pattern"/> or <paramref name="escape"/> does not have a string result type.</exception>
977 public static DbLikeExpression
Like(this DbExpression argument
, DbExpression pattern
, DbExpression escape
)
979 TypeUsage resultType
= ArgumentValidation
.ValidateLike(argument
, pattern
, escape
);
980 return new DbLikeExpression(resultType
, argument
, pattern
, escape
);
985 #region Type Operators - Cast, Treat, OfType, OfTypeOnly, IsOf, IsOfOnly
988 /// Creates a new <see cref="DbCastExpression"/> that applies a cast operation to a polymorphic argument.
990 /// <param name="argument">The argument to which the cast should be applied.</param>
991 /// <param name="toType">Type metadata that specifies the type to cast to.</param>
992 /// <returns>A new DbCastExpression with the specified argument and target type.</returns>
993 /// <exception cref="ArgumentNullException"><paramref name="argument"/> or <paramref name="toType"/> is null</exception>
994 /// <exception cref="ArgumentException">The specified cast is not valid.</exception>
995 public static DbCastExpression
CastTo(this DbExpression argument
, TypeUsage toType
)
997 ArgumentValidation
.ValidateCastTo(argument
, toType
);
998 return new DbCastExpression(toType
, argument
);
1002 /// Creates a new <see cref="DbTreatExpression"/>.
1004 /// <param name="argument">An expression that specifies the instance.</param>
1005 /// <param name="treatType">Type metadata for the treat-as type.</param>
1006 /// <returns>A new DbTreatExpression with the specified argument and type.</returns>
1007 /// <exception cref="ArgumentNullException"><paramref name="argument"/> or <paramref name="treatType"/> is null</exception>
1008 /// <exception cref="ArgumentException"><paramref name="treatType"/> is not in the same type hierarchy as the result type of <paramref name="argument"/>.
1011 /// DbTreatExpression requires that <paramref name="argument"/> has a polymorphic result type,
1012 /// and that <paramref name="treatType"/> is a type from the same type hierarchy as that result type.
1014 public static DbTreatExpression
TreatAs(this DbExpression argument
, TypeUsage treatType
)
1016 ArgumentValidation
.ValidateTreatAs(argument
, treatType
);
1017 return new DbTreatExpression(treatType
, argument
);
1021 /// Creates a new <see cref="DbOfTypeExpression"/> that produces a set consisting of the elements of the given input set that are of the specified type.
1023 /// <param name="argument">A <see cref="DbExpression"/> that specifies the input set.</param>
1024 /// <param name="type">Type metadata for the type that elements of the input set must have to be included in the resulting set.</param>
1025 /// <returns>A new DbOfTypeExpression with the specified set argument and type, and an ExpressionKind of <see cref="DbExpressionKind.OfType"/>.</returns>
1026 /// <exception cref="ArgumentNullException"><paramref name="argument"/> or <paramref name="type"/> is null</exception>
1027 /// <exception cref="ArgumentException">
1028 /// <paramref name="argument"/> does not have a collection result type, or
1029 /// <paramref name="type"/> is not a type in the same type hierarchy as the element type of the
1030 /// collection result type of <paramref name="argument"/>.
1033 /// DbOfTypeExpression requires that <paramref name="argument"/> has a collection result type with
1034 /// a polymorphic element type, and that <paramref name="type"/> is a type from the same type hierarchy as that element type.
1036 public static DbOfTypeExpression
OfType(this DbExpression argument
, TypeUsage type
)
1038 TypeUsage collectionOfTypeResultType
= ArgumentValidation
.ValidateOfType(argument
, type
);
1039 return new DbOfTypeExpression(DbExpressionKind
.OfType
, collectionOfTypeResultType
, argument
, type
);
1043 /// Creates a new <see cref="DbOfTypeExpression"/> that produces a set consisting of the elements of the given input set that are of exactly the specified type.
1045 /// <param name="argument">An <see cref="DbExpression"/> that specifies the input set.</param>
1046 /// <param name="type">Type metadata for the type that elements of the input set must match exactly to be included in the resulting set.</param>
1047 /// <returns>A new DbOfTypeExpression with the specified set argument and type, and an ExpressionKind of <see cref="DbExpressionKind.OfTypeOnly"/>.</returns>
1048 /// <exception cref="ArgumentNullException"><paramref name="argument"/> or <paramref name="type"/> is null</exception>
1049 /// <exception cref="ArgumentException">
1050 /// <paramref name="argument"/> does not have a collection result type, or
1051 /// <paramref name="type"/> is not a type in the same type hierarchy as the element type of the
1052 /// collection result type of <paramref name="argument"/>.
1055 /// DbOfTypeExpression requires that <paramref name="argument"/> has a collection result type with
1056 /// a polymorphic element type, and that <paramref name="type"/> is a type from the same type hierarchy as that element type.
1058 public static DbOfTypeExpression
OfTypeOnly(this DbExpression argument
, TypeUsage type
)
1060 TypeUsage collectionOfTypeResultType
= ArgumentValidation
.ValidateOfType(argument
, type
);
1061 return new DbOfTypeExpression(DbExpressionKind
.OfTypeOnly
, collectionOfTypeResultType
, argument
, type
);
1065 /// Creates a new <see cref="DbIsOfExpression"/> that determines whether the given argument is of the specified type or a subtype.
1067 /// <param name="argument">An expression that specifies the instance.</param>
1068 /// <param name="type">Type metadata that specifies the type that the instance's result type should be compared to.</param>
1069 /// <returns>A new DbIsOfExpression with the specified instance and type and DbExpressionKind IsOf.</returns>
1070 /// <exception cref="ArgumentNullException"><paramref name="argument"/> or <paramref name="type"/> is null</exception>
1071 /// <exception cref="ArgumentException">
1072 /// <paramref name="type"/> is not in the same type hierarchy as the result type of <paramref name="argument"/>.
1075 /// DbIsOfExpression requires that <paramref name="argument"/> has a polymorphic result type,
1076 /// and that <paramref name="type"/> is a type from the same type hierarchy as that result type.
1078 public static DbIsOfExpression
IsOf(this DbExpression argument
, TypeUsage type
)
1080 TypeUsage booleanResultType
= ArgumentValidation
.ValidateIsOf(argument
, type
);
1081 return new DbIsOfExpression(DbExpressionKind
.IsOf
, booleanResultType
, argument
, type
);
1085 /// Creates a new <see cref="DbIsOfExpression"/> expression that determines whether the given argument is of the specified type, and only that type (not a subtype).
1087 /// <param name="argument">An expression that specifies the instance.</param>
1088 /// <param name="type">Type metadata that specifies the type that the instance's result type should be compared to.</param>
1089 /// <returns>A new DbIsOfExpression with the specified instance and type and DbExpressionKind IsOfOnly.</returns>
1090 /// <exception cref="ArgumentNullException"><paramref name="argument"/> or <paramref name="type"/> is null</exception>
1091 /// <exception cref="ArgumentException">
1092 /// <paramref name="type"/> is not in the same type hierarchy as the result type of <paramref name="argument"/>.
1095 /// DbIsOfExpression requires that <paramref name="argument"/> has a polymorphic result type,
1096 /// and that <paramref name="type"/> is a type from the same type hierarchy as that result type.
1098 public static DbIsOfExpression
IsOfOnly(this DbExpression argument
, TypeUsage type
)
1100 TypeUsage booleanResultType
= ArgumentValidation
.ValidateIsOf(argument
, type
);
1101 return new DbIsOfExpression(DbExpressionKind
.IsOfOnly
, booleanResultType
, argument
, type
);
1106 #region Ref Operators - Deref, EntityRef, Ref, RefKey, RelationshipNavigation
1109 /// Creates a new <see cref="DbDerefExpression"/> that retrieves a specific Entity given a reference expression
1111 /// <param name="argument">An <see cref="DbExpression"/> that provides the reference. This expression must have a reference Type</param>
1112 /// <returns>A new DbDerefExpression that retrieves the specified Entity</returns>
1113 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
1114 /// <exception cref="ArgumentException"><paramref name="argument"/> does not have a reference result type.</exception>
1115 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Deref")]
1116 public static DbDerefExpression
Deref(this DbExpression argument
)
1118 TypeUsage entityResultType
= ArgumentValidation
.ValidateDeref(argument
);
1119 return new DbDerefExpression(entityResultType
, argument
);
1123 /// Creates a new <see cref="DbEntityRefExpression"/> that retrieves the ref of the specifed entity in structural form.
1125 /// <param name="argument">The expression that provides the entity. This expression must have an entity result type.</param>
1126 /// <returns>A new DbEntityRefExpression that retrieves a reference to the specified entity.</returns>
1127 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
1128 /// <exception cref="ArgumentException"><paramref name="argument"/> does not have an entity result type.</exception>
1129 public static DbEntityRefExpression
GetEntityRef(this DbExpression argument
)
1131 TypeUsage refResultType
= ArgumentValidation
.ValidateGetEntityRef(argument
);
1132 return new DbEntityRefExpression(refResultType
, argument
);
1136 /// Creates a new <see cref="DbRefExpression"/> that encodes a reference to a specific entity based on key values.
1138 /// <param name="entitySet">The entity set in which the referenced element resides.</param>
1139 /// <param name="keyValues">A collection of <see cref="DbExpression"/>s that provide the key values. These expressions must match (in number, type, and order) the key properties of the referenced entity type.</param>
1140 /// <returns>A new DbRefExpression that references the element with the specified key values in the given entity set.</returns>
1141 /// <exception cref="ArgumentNullException"><paramref name="entitySet"/> is null, or <paramref name="keyValues"/> is null or contains null.</exception>
1142 /// <exception cref="ArgumentException">
1143 /// The count of <paramref name="keyValues"/> does not match the count of key members declared by the <paramref name="entitySet"/>'s element type,
1144 /// or <paramref name="keyValues"/> contains an expression with a result type that is not compatible with the type of the corresponding key member.
1146 public static DbRefExpression
CreateRef(this EntitySet entitySet
, IEnumerable
<DbExpression
> keyValues
)
1148 return CreateRefExpression(entitySet
, keyValues
);
1152 /// Creates a new <see cref="DbRefExpression"/> that encodes a reference to a specific entity based on key values.
1154 /// <param name="entitySet">The entity set in which the referenced element resides.</param>
1155 /// <param name="keyValues">A collection of <see cref="DbExpression"/>s that provide the key values. These expressions must match (in number, type, and order) the key properties of the referenced entity type.</param>
1156 /// <returns>A new DbRefExpression that references the element with the specified key values in the given entity set.</returns>
1157 /// <exception cref="ArgumentNullException"><paramref name="entitySet"/> is null, or <paramref name="keyValues"/> is null or contains null.</exception>
1158 /// <exception cref="ArgumentException">
1159 /// The count of <paramref name="keyValues"/> does not match the count of key members declared by the <paramref name="entitySet"/>'s element type,
1160 /// or <paramref name="keyValues"/> contains an expression with a result type that is not compatible with the type of the corresponding key member.
1162 public static DbRefExpression
CreateRef(this EntitySet entitySet
, params DbExpression
[] keyValues
)
1164 return CreateRefExpression(entitySet
, keyValues
);
1168 /// Creates a new <see cref="DbRefExpression"/> that encodes a reference to a specific entity of a given type based on key values.
1170 /// <param name="entitySet">The entity set in which the referenced element resides.</param>
1171 /// <param name="entityType">The specific type of the referenced entity. This must be an entity type from the same hierarchy as the entity set's element type.</param>
1172 /// <param name="keyValues">A collection of <see cref="DbExpression"/>s that provide the key values. These expressions must match (in number, type, and order) the key properties of the referenced entity type.</param>
1173 /// <returns>A new DbRefExpression that references the element with the specified key values in the given entity set.</returns>
1174 /// <exception cref="ArgumentNullException"><paramref name="entitySet"/> or <paramref name="entityType"/> is null, or <paramref name="keyValues"/> is null or contains null.</exception>
1175 /// <exception cref="ArgumentException"><paramref name="entityType"/> is not from the same type hierarchy (a subtype, supertype, or the same type) as <paramref name="entitySet"/>'s element type.</exception>
1176 /// <exception cref="ArgumentException">
1177 /// The count of <paramref name="keyValues"/> does not match the count of key members declared by the <paramref name="entitySet"/>'s element type,
1178 /// or <paramref name="keyValues"/> contains an expression with a result type that is not compatible with the type of the corresponding key member.
1180 public static DbRefExpression
CreateRef(this EntitySet entitySet
, EntityType entityType
, IEnumerable
<DbExpression
> keyValues
)
1182 return CreateRefExpression(entitySet
, entityType
, keyValues
);
1186 /// Creates a new <see cref="DbRefExpression"/> that encodes a reference to a specific entity of a given type based on key values.
1188 /// <param name="entitySet">The entity set in which the referenced element resides.</param>
1189 /// <param name="entityType">The specific type of the referenced entity. This must be an entity type from the same hierarchy as the entity set's element type.</param>
1190 /// <param name="keyValues">A collection of <see cref="DbExpression"/>s that provide the key values. These expressions must match (in number, type, and order) the key properties of the referenced entity type.</param>
1191 /// <returns>A new DbRefExpression that references the element with the specified key values in the given entity set.</returns>
1192 /// <exception cref="ArgumentNullException"><paramref name="entitySet"/> or <paramref name="entityType"/> is null, or <paramref name="keyValues"/> is null or contains null.</exception>
1193 /// <exception cref="ArgumentException"><paramref name="entityType"/> is not from the same type hierarchy (a subtype, supertype, or the same type) as <paramref name="entitySet"/>'s element type.</exception>
1194 /// <exception cref="ArgumentException">
1195 /// The count of <paramref name="keyValues"/> does not match the count of key members declared by the <paramref name="entitySet"/>'s element type,
1196 /// or <paramref name="keyValues"/> contains an expression with a result type that is not compatible with the type of the corresponding key member.
1198 public static DbRefExpression
CreateRef(this EntitySet entitySet
, EntityType entityType
, params DbExpression
[] keyValues
)
1200 return CreateRefExpression(entitySet
, entityType
, keyValues
);
1203 private static DbRefExpression
CreateRefExpression(EntitySet entitySet
, IEnumerable
<DbExpression
> keyValues
)
1205 DbExpression keyConstructor
;
1206 TypeUsage refResultType
= ArgumentValidation
.ValidateCreateRef(entitySet
, keyValues
, out keyConstructor
);
1207 return new DbRefExpression(refResultType
, entitySet
, keyConstructor
);
1210 private static DbRefExpression
CreateRefExpression(EntitySet entitySet
, EntityType entityType
, IEnumerable
<DbExpression
> keyValues
)
1212 DbExpression keyConstructor
;
1213 TypeUsage refResultType
= ArgumentValidation
.ValidateCreateRef(entitySet
, entityType
, keyValues
, out keyConstructor
);
1214 return new DbRefExpression(refResultType
, entitySet
, keyConstructor
);
1218 /// Creates a new <see cref="DbRefExpression"/> that encodes a reference to a specific Entity based on key values.
1220 /// <param name="entitySet">The Entity set in which the referenced element resides.</param>
1221 /// <param name="keyRow">A <see cref="DbExpression"/> that constructs a record with columns that match (in number, type, and order) the Key properties of the referenced Entity type.</param>
1222 /// <returns>A new DbRefExpression that references the element with the specified key values in the given Entity set.</returns>
1223 /// <exception cref="ArgumentNullException"><paramref name="entitySet"/> or <paramref name="keyRow"/> is null</exception>
1224 /// <exception cref="ArgumentException">
1225 /// <paramref name="keyRow"/> does not have a record result type that matches the key properties of the referenced entity set's entity type.
1228 /// <paramref name="keyRow"/> should be an expression that specifies the key values that identify the referenced entity within the given entity set.
1229 /// The result type of <paramref name="keyRow"/> should contain a corresponding column for each key property defined by <paramref name="entitySet"/>'s entity type.
1231 public static DbRefExpression
RefFromKey(this EntitySet entitySet
, DbExpression keyRow
)
1233 TypeUsage refResultType
= ArgumentValidation
.ValidateRefFromKey(entitySet
, keyRow
);
1234 return new DbRefExpression(refResultType
, entitySet
, keyRow
);
1238 /// Creates a new <see cref="DbRefExpression"/> that encodes a reference to a specific Entity based on key values.
1240 /// <param name="entitySet">The Entity set in which the referenced element resides.</param>
1241 /// <param name="keyRow">A <see cref="DbExpression"/> that constructs a record with columns that match (in number, type, and order) the Key properties of the referenced Entity type.</param>
1242 /// <param name="entityType">The type of the Entity that the reference should refer to.</param>
1243 /// <returns>A new DbRefExpression that references the element with the specified key values in the given Entity set.</returns>
1244 /// <exception cref="ArgumentNullException"><paramref name="entitySet"/>, <paramref name="keyRow"/> or <paramref name="entityType"/> is null</exception>
1245 /// <exception cref="ArgumentException">
1246 /// <paramref name="entityType"/> is not in the same type hierarchy as the entity set's entity type, or <paramref name="keyRow"/> does not have a
1247 /// record result type that matches the key properties of the referenced entity set's entity type.
1250 /// <paramref name="keyRow"/> should be an expression that specifies the key values that identify the referenced entity within the given entity set.
1251 /// The result type of <paramref name="keyRow"/> should contain a corresponding column for each key property defined by <paramref name="entitySet"/>'s entity type.
1253 public static DbRefExpression
RefFromKey(this EntitySet entitySet
, DbExpression keyRow
, EntityType entityType
)
1255 TypeUsage refResultType
= ArgumentValidation
.ValidateRefFromKey(entitySet
, keyRow
, entityType
);
1256 return new DbRefExpression(refResultType
, entitySet
, keyRow
);
1260 /// Creates a new <see cref="DbRefKeyExpression"/> that retrieves the key values of the specifed reference in structural form.
1262 /// <param name="argument">The expression that provides the reference. This expression must have a reference Type with an Entity element type.</param>
1263 /// <returns>A new DbRefKeyExpression that retrieves the key values of the specified reference.</returns>
1264 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
1265 /// <exception cref="ArgumentException"><paramref name="argument"/> does not have a reference result type.</exception>
1266 public static DbRefKeyExpression
GetRefKey(this DbExpression argument
)
1268 TypeUsage rowResultType
= ArgumentValidation
.ValidateGetRefKey(argument
);
1269 return new DbRefKeyExpression(rowResultType
, argument
);
1273 /// Creates a new <see cref="DbRelationshipNavigationExpression"/> representing the navigation of a composition or association relationship.
1275 /// <param name="navigateFrom">An expression the specifies the instance from which navigation should occur</param>
1276 /// <param name="fromEnd">Metadata for the property that represents the end of the relationship from which navigation should occur</param>
1277 /// <param name="toEnd">Metadata for the property that represents the end of the relationship to which navigation should occur</param>
1278 /// <returns>A new DbRelationshipNavigationExpression representing the navigation of the specified from and to relation ends of the specified relation type from the specified navigation source instance</returns>
1279 /// <exception cref="ArgumentNullException"><paramref name="fromEnd"/>, <paramref name="toEnd"/> or <paramref name="navigateFrom"/> is null</exception>
1280 /// <exception cref="ArgumentException">
1281 /// <paramref name="fromEnd"/> and <paramref name="toEnd"/> are not declared by the same relationship type, or
1282 /// <paramref name="navigateFrom"/> has a result type that is not compatible with the property type of <paramref name="fromEnd"/>.
1285 /// <see cref="DbRelationshipNavigationExpression"/> requires that navigation always occur from a reference, and so <paramref name="navigateFrom"/> must always have a reference result type.
1287 public static DbRelationshipNavigationExpression
Navigate(this DbExpression navigateFrom
, RelationshipEndMember fromEnd
, RelationshipEndMember toEnd
)
1289 RelationshipType relType
;
1290 TypeUsage resultType
= ArgumentValidation
.ValidateNavigate(navigateFrom
, fromEnd
, toEnd
, out relType
, allowAllRelationshipsInSameTypeHierarchy
: false);
1291 return new DbRelationshipNavigationExpression(resultType
, relType
, fromEnd
, toEnd
, navigateFrom
);
1295 /// Creates a new <see cref="DbRelationshipNavigationExpression"/> representing the navigation of a composition or association relationship.
1297 /// <param name="type">Metadata for the relation type that represents the relationship</param>
1298 /// <param name="fromEndName">The name of the property of the relation type that represents the end of the relationship from which navigation should occur</param>
1299 /// <param name="toEndName">The name of the property of the relation type that represents the end of the relationship to which navigation should occur</param>
1300 /// <param name="navigateFrom">An expression the specifies the instance from which naviagtion should occur</param>
1301 /// <returns>A new DbRelationshipNavigationExpression representing the navigation of the specified from and to relation ends of the specified relation type from the specified navigation source instance</returns>
1302 /// <exception cref="ArgumentNullException">
1303 /// <paramref name="type"/>, <paramref name="fromEndName"/>, <paramref name="toEndName"/> or <paramref name="navigateFrom"/> is null.
1305 /// <exception cref="ArgumentException">
1306 /// <paramref name="type"/> is not associated with this command tree's metadata workspace or <paramref name="navigateFrom"/> is associated with a different command tree,
1307 /// or <paramref name="type"/> does not declare a relation end property with name <paramref name="toEndName"/> or <paramref name="fromEndName"/>,
1308 /// or <paramref name="navigateFrom"/> has a result type that is not compatible with the property type of the relation end property with name <paramref name="fromEndName"/>.
1311 /// <see cref="DbRelationshipNavigationExpression"/> requires that navigation always occur from a reference, and so <paramref name="navigateFrom"/> must always have a reference result type.
1313 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
1314 public static DbRelationshipNavigationExpression
Navigate(this RelationshipType type
, string fromEndName
, string toEndName
, DbExpression navigateFrom
)
1316 RelationshipEndMember fromEnd
;
1317 RelationshipEndMember toEnd
;
1318 TypeUsage resultType
= ArgumentValidation
.ValidateNavigate(navigateFrom
, type
, fromEndName
, toEndName
, out fromEnd
, out toEnd
);
1319 return new DbRelationshipNavigationExpression(resultType
, type
, fromEnd
, toEnd
, navigateFrom
);
1324 #region Unary and Binary Set Operators - Distinct, Element, IsEmpty, Except, Intersect, UnionAll, Limit
1327 /// Creates a new <see cref="DbDistinctExpression"/> that removes duplicates from the given set argument.
1329 /// <param name="argument">An expression that defines the set over which to perfom the distinct operation.</param>
1330 /// <returns>A new DbDistinctExpression that represents the distinct operation applied to the specified set argument.</returns>
1331 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
1332 /// <exception cref="ArgumentException"><paramref name="argument"/> does not have a collection result type.</exception>
1333 public static DbDistinctExpression
Distinct(this DbExpression argument
)
1335 TypeUsage resultType
= ArgumentValidation
.ValidateDistinct(argument
);
1336 return new DbDistinctExpression(resultType
, argument
);
1340 /// Creates a new <see cref="DbElementExpression"/> that converts a set into a singleton.
1342 /// <param name="argument">An expression that specifies the input set.</param>
1343 /// <returns>A DbElementExpression that represents the conversion of the set argument to a singleton.</returns>
1344 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
1345 /// <exception cref="ArgumentException"><paramref name="argument"/> does not have a collection result type.</exception>
1346 public static DbElementExpression
Element(this DbExpression argument
)
1348 TypeUsage resultType
= ArgumentValidation
.ValidateElement(argument
);
1349 return new DbElementExpression(resultType
, argument
);
1353 /// Creates a new <see cref="DbIsEmptyExpression"/> that determines whether the specified set argument is an empty set.
1355 /// <param name="argument">An expression that specifies the input set</param>
1356 /// <returns>A new DbIsEmptyExpression with the specified argument.</returns>
1357 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
1358 /// <exception cref="ArgumentException"><paramref name="argument"/> does not have a collection result type.</exception>
1359 public static DbIsEmptyExpression
IsEmpty(this DbExpression argument
)
1361 TypeUsage booleanResultType
= ArgumentValidation
.ValidateIsEmpty(argument
);
1362 return new DbIsEmptyExpression(booleanResultType
, argument
);
1366 /// Creates a new <see cref="DbExceptExpression"/> that computes the subtraction of the right set argument from the left set argument.
1368 /// <param name="left">An expression that defines the left set argument.</param>
1369 /// <param name="right">An expression that defines the right set argument.</param>
1370 /// <returns>A new DbExceptExpression that represents the difference of the left argument from the right argument.</returns>
1371 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
1372 /// <exception cref="ArgumentException">No common collection result type exists between <paramref name="left"/> and <paramref name="right"/>.</exception>
1373 public static DbExceptExpression
Except(this DbExpression left
, DbExpression right
)
1375 TypeUsage resultType
= ArgumentValidation
.ValidateExcept(left
, right
);
1376 return new DbExceptExpression(resultType
, left
, right
);
1380 /// Creates a new <see cref="DbIntersectExpression"/> that computes the intersection of the left and right set arguments.
1382 /// <param name="left">An expression that defines the left set argument.</param>
1383 /// <param name="right">An expression that defines the right set argument.</param>
1384 /// <returns>A new DbIntersectExpression that represents the intersection of the left and right arguments.</returns>
1385 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
1386 /// <exception cref="ArgumentException">No common collection result type exists between <paramref name="left"/> and <paramref name="right"/>.</exception>
1387 public static DbIntersectExpression
Intersect(this DbExpression left
, DbExpression right
)
1389 TypeUsage resultType
= ArgumentValidation
.ValidateIntersect(left
, right
);
1390 return new DbIntersectExpression(resultType
, left
, right
);
1394 /// Creates a new <see cref="DbUnionAllExpression"/> that computes the union of the left and right set arguments and does not remove duplicates.
1396 /// <param name="left">An expression that defines the left set argument.</param>
1397 /// <param name="right">An expression that defines the right set argument.</param>
1398 /// <returns>A new DbUnionAllExpression that union, including duplicates, of the the left and right arguments.</returns>
1399 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
1400 /// <exception cref="ArgumentException">No common collection result type exists between <paramref name="left"/> and <paramref name="right"/>.</exception>
1401 public static DbUnionAllExpression
UnionAll(this DbExpression left
, DbExpression right
)
1403 TypeUsage resultType
= ArgumentValidation
.ValidateUnionAll(left
, right
);
1404 return new DbUnionAllExpression(resultType
, left
, right
);
1408 /// Creates a new <see cref="DbLimitExpression"/> that restricts the number of elements in the Argument collection to the specified count Limit value.
1409 /// Tied results are not included in the output.
1411 /// <param name="argument">An expression that specifies the input collection.</param>
1412 /// <param name="count">An expression that specifies the limit value.</param>
1413 /// <returns>A new DbLimitExpression with the specified argument and count limit values that does not include tied results.</returns>
1414 /// <exception cref="ArgumentNullException"><paramref name="argument"/> or <paramref name="count"/> is null</exception>
1415 /// <exception cref="ArgumentException">
1416 /// <paramref name="argument"/> does not have a collection result type,
1417 /// or <paramref name="count"/> does not have a result type that is equal or promotable to a 64-bit integer type.
1419 public static DbLimitExpression
Limit(this DbExpression argument
, DbExpression count
)
1421 TypeUsage resultType
= ArgumentValidation
.ValidateLimit(argument
, count
);
1422 return new DbLimitExpression(resultType
, argument
, count
, false);
1427 #region General Operators - Case, Function, NewInstance, Property
1430 /// Creates a new <see cref="DbCaseExpression"/>.
1432 /// <param name="whenExpressions">A list of expressions that provide the conditional for of each case.</param>
1433 /// <param name="thenExpressions">A list of expressions that provide the result of each case.</param>
1434 /// <param name="elseExpression">An expression that defines the result when no case is matched.</param>
1435 /// <returns>A new DbCaseExpression with the specified cases and default result.</returns>
1436 /// <exception cref="ArgumentNullException">
1437 /// <paramref name="whenExpressions"/> or <paramref name="thenExpressions"/> is null or contains null,
1438 /// or <paramref name="elseExpression"/> is null.
1440 /// <exception cref="ArgumentException">
1441 /// <paramref name="whenExpressions"/> or <paramref name="thenExpressions"/> is empty or <paramref name="whenExpressions"/> contains an expression with a non-Boolean result type, or
1442 /// No common result type exists for all expressions in <paramref name="thenExpressions"/> and <paramref name="elseExpression"/>.
1444 public static DbCaseExpression
Case(IEnumerable
<DbExpression
> whenExpressions
, IEnumerable
<DbExpression
> thenExpressions
, DbExpression elseExpression
)
1446 DbExpressionList validWhens
;
1447 DbExpressionList validThens
;
1448 TypeUsage resultType
= ArgumentValidation
.ValidateCase(whenExpressions
, thenExpressions
, elseExpression
, out validWhens
, out validThens
);
1449 return new DbCaseExpression(resultType
, validWhens
, validThens
, elseExpression
);
1453 /// Creates a new <see cref="DbFunctionExpression"/> representing the invocation of the specified function with the given arguments.
1455 /// <param name="function">Metadata for the function to invoke.</param>
1456 /// <param name="arguments">A list of expressions that provide the arguments to the function.</param>
1457 /// <returns>A new DbFunctionExpression representing the function invocation.</returns>
1458 /// <exception cref="ArgumentNullException">
1459 /// <paramref name="function"/> is null, or <paramref name="arguments"/> is null or contains null.
1461 /// <exception cref="ArgumentException">
1462 /// The count of <paramref name="arguments"/> does not equal the number of parameters declared by <paramref name="function"/>,
1463 /// or <paramref name="arguments"/> contains an expression that has a result type that is not equal or promotable
1464 /// to the corresponding function parameter type.
1466 public static DbFunctionExpression
Invoke(this EdmFunction function
, IEnumerable
<DbExpression
> arguments
)
1468 return InvokeFunction(function
, arguments
);
1472 /// Creates a new <see cref="DbFunctionExpression"/> representing the invocation of the specified function with the given arguments.
1474 /// <param name="function">Metadata for the function to invoke.</param>
1475 /// <param name="arguments">Expressions that provide the arguments to the function.</param>
1476 /// <returns>A new DbFunctionExpression representing the function invocation.</returns>
1477 /// <exception cref="ArgumentNullException">
1478 /// <paramref name="function"/> is null, or <paramref name="arguments"/> is null or contains null.
1480 /// <exception cref="ArgumentException">
1481 /// The count of <paramref name="arguments"/> does not equal the number of parameters declared by <paramref name="function"/>,
1482 /// or <paramref name="arguments"/> contains an expression that has a result type that is not equal or promotable
1483 /// to the corresponding function parameter type.
1485 public static DbFunctionExpression
Invoke(this EdmFunction function
, params DbExpression
[] arguments
)
1487 return InvokeFunction(function
, arguments
);
1490 private static DbFunctionExpression
InvokeFunction(EdmFunction function
, IEnumerable
<DbExpression
> arguments
)
1492 DbExpressionList validArguments
;
1493 TypeUsage resultType
= ArgumentValidation
.ValidateFunction(function
, arguments
, out validArguments
);
1494 return new DbFunctionExpression(resultType
, function
, validArguments
);
1498 /// Creates a new <see cref="DbLambdaExpression"/> representing the application of the specified Lambda function to the given arguments.
1500 /// <param name="lambda">A <see cref="DbLambda"/> instance representing the Lambda function to apply.</param>
1501 /// <param name="arguments">A list of expressions that provide the arguments.</param>
1502 /// <returns>A new DbLambdaExpression representing the Lambda function application.</returns>
1503 /// <exception cref="ArgumentNullException">
1504 /// <paramref name="lambda"/> is null, or <paramref name="arguments"/> is null or contains null.
1506 /// <exception cref="ArgumentException">
1507 /// The count of <paramref name="arguments"/> does not equal the number of variables declared by <paramref name="lambda"/>,
1508 /// or <paramref name="arguments"/> contains an expression that has a result type that is not equal or promotable
1509 /// to the corresponding variable type.
1511 public static DbLambdaExpression
Invoke(this DbLambda lambda
, IEnumerable
<DbExpression
> arguments
)
1513 return InvokeLambda(lambda
, arguments
);
1517 /// Creates a new <see cref="DbLambdaExpression"/> representing the application of the specified Lambda function to the given arguments.
1519 /// <param name="lambda">A <see cref="DbLambda"/> instance representing the Lambda function to apply.</param>
1520 /// <param name="arguments">Expressions that provide the arguments.</param>
1521 /// <returns>A new DbLambdaExpression representing the Lambda function application.</returns>
1522 /// <exception cref="ArgumentNullException">
1523 /// <paramref name="lambda"/> is null, or <paramref name="arguments"/> is null or contains null.
1525 /// <exception cref="ArgumentException">
1526 /// The count of <paramref name="arguments"/> does not equal the number of variables declared by <paramref name="lambda"/>,
1527 /// or <paramref name="arguments"/> contains an expression that has a result type that is not equal or promotable
1528 /// to the corresponding variable type.
1530 public static DbLambdaExpression
Invoke(this DbLambda lambda
, params DbExpression
[] arguments
)
1532 return InvokeLambda(lambda
, arguments
);
1535 private static DbLambdaExpression
InvokeLambda(DbLambda lambda
, IEnumerable
<DbExpression
> arguments
)
1537 DbExpressionList validArguments
;
1538 TypeUsage resultType
= ArgumentValidation
.ValidateInvoke(lambda
, arguments
, out validArguments
);
1539 return new DbLambdaExpression(resultType
, lambda
, validArguments
);
1543 /// Creates a new <see cref="DbNewInstanceExpression"/>. If the type argument is a collection type, the arguments specify the elements of the collection. Otherwise the arguments are used as property or column values in the new instance.
1545 /// <param name="instanceType">The type of the new instance.</param>
1546 /// <param name="arguments">Expressions that specify values of the new instances, interpreted according to the instance's type.</param>
1547 /// <returns>A new DbNewInstanceExpression with the specified type and arguments.</returns>
1548 /// <exception cref="ArgumentNullException"><paramref name="instanceType"/> or <paramref name="arguments"/> is null, or <paramref name="arguments"/> contains null</exception>
1549 /// <exception cref="ArgumentException">
1550 /// <paramref name="arguments"/> is empty or the result types of the contained expressions do not match the requirements of <paramref name="instanceType"/> (as explained in the remarks section).
1554 /// if <paramref name="instanceType"/> is a a collection type then every expression in <paramref name="arguments"/> must have a result type that is promotable to the element type of the <paramref name="instanceType"/>.
1557 /// if <paramref name="instanceType"/> is a row type, <paramref name="arguments"/> must contain as many expressions as there are columns in the row
1558 /// type, and the result type of each expression must be equal or promotable to the type of the corresponding column. A row type that does not declare any columns is invalid.
1561 /// if <paramref name="instanceType"/> is an entity type, <paramref name="arguments"/> must contain as many expressions as there are properties defined by the type,
1562 /// and the result type of each expression must be equal or promotable to the type of the corresponding property.
1565 public static DbNewInstanceExpression
New(this TypeUsage instanceType
, IEnumerable
<DbExpression
> arguments
)
1567 return NewInstance(instanceType
, arguments
);
1571 /// Creates a new <see cref="DbNewInstanceExpression"/>. If the type argument is a collection type, the arguments specify the elements of the collection. Otherwise the arguments are used as property or column values in the new instance.
1573 /// <param name="instanceType">The type of the new instance.</param>
1574 /// <param name="arguments">Expressions that specify values of the new instances, interpreted according to the instance's type.</param>
1575 /// <returns>A new DbNewInstanceExpression with the specified type and arguments.</returns>
1576 /// <exception cref="ArgumentNullException"><paramref name="instanceType"/> or <paramref name="arguments"/> is null, or <paramref name="arguments"/> contains null</exception>
1577 /// <exception cref="ArgumentException">
1578 /// <paramref name="arguments"/> is empty or the result types of the contained expressions do not match the requirements of <paramref name="instanceType"/> (as explained in the remarks section).
1582 /// if <paramref name="instanceType"/> is a a collection type then every expression in <paramref name="arguments"/> must have a result type that is promotable to the element type of the <paramref name="instanceType"/>.
1585 /// if <paramref name="instanceType"/> is a row type, <paramref name="arguments"/> must contain as many expressions as there are columns in the row
1586 /// type, and the result type of each expression must be equal or promotable to the type of the corresponding column. A row type that does not declare any columns is invalid.
1589 /// if <paramref name="instanceType"/> is an entity type, <paramref name="arguments"/> must contain as many expressions as there are properties defined by the type,
1590 /// and the result type of each expression must be equal or promotable to the type of the corresponding property.
1593 public static DbNewInstanceExpression
New(this TypeUsage instanceType
, params DbExpression
[] arguments
)
1595 return NewInstance(instanceType
, arguments
);
1598 private static DbNewInstanceExpression
NewInstance(TypeUsage instanceType
, IEnumerable
<DbExpression
> arguments
)
1600 DbExpressionList validArguments
;
1601 TypeUsage resultType
= ArgumentValidation
.ValidateNew(instanceType
, arguments
, out validArguments
);
1602 return new DbNewInstanceExpression(resultType
, validArguments
);
1606 /// Creates a new <see cref="DbNewInstanceExpression"/> that constructs a collection containing the specified elements. The type of the collection is based on the common type of the elements. If no common element type exists an exception is thrown.
1608 /// <param name="elements">A list of expressions that provide the elements of the collection</param>
1609 /// <returns>A new DbNewInstanceExpression with the specified collection type and arguments.</returns>
1610 /// <exception cref="ArgumentNullException"><paramref name="elements"/> is null, or contains null</exception>
1611 /// <exception cref="ArgumentException">
1612 /// <paramref name="elements"/> is empty or contains expressions for which no common result type exists.
1614 public static DbNewInstanceExpression
NewCollection(IEnumerable
<DbExpression
> elements
)
1616 return CreateNewCollection(elements
);
1620 /// Creates a new <see cref="DbNewInstanceExpression"/> that constructs a collection containing the specified elements. The type of the collection is based on the common type of the elements. If no common element type exists an exception is thrown.
1622 /// <param name="elements">A list of expressions that provide the elements of the collection</param>
1623 /// <returns>A new DbNewInstanceExpression with the specified collection type and arguments.</returns>
1624 /// <exception cref="ArgumentNullException"><paramref name="elements"/> is null, or contains null</exception>
1625 /// <exception cref="ArgumentException">
1626 /// <paramref name="elements"/> is empty or contains expressions for which no common result type exists.
1628 public static DbNewInstanceExpression
NewCollection(params DbExpression
[] elements
)
1630 return CreateNewCollection(elements
);
1633 private static DbNewInstanceExpression
CreateNewCollection(IEnumerable
<DbExpression
> elements
)
1635 DbExpressionList validElements
;
1636 TypeUsage collectionResultType
= ArgumentValidation
.ValidateNewCollection(elements
, out validElements
);
1637 return new DbNewInstanceExpression(collectionResultType
, validElements
);
1641 /// Creates a new <see cref="DbNewInstanceExpression"/> that constructs an empty collection of the specified collection type.
1643 /// <param name="collectionType">The type metadata for the collection to create</param>
1644 /// <returns>A new DbNewInstanceExpression with the specified collection type and an empty <code>Arguments</code> list.</returns>
1645 /// <exception cref="ArgumentNullException"><paramref name="collectionType"/> is null</exception>
1646 /// <exception cref="ArgumentException"><paramref name="collectionType"/> is not a collection type</exception>
1647 public static DbNewInstanceExpression
NewEmptyCollection(this TypeUsage collectionType
)
1649 DbExpressionList validElements
;
1650 TypeUsage validResultType
= ArgumentValidation
.ValidateNewEmptyCollection(collectionType
, out validElements
);
1651 return new DbNewInstanceExpression(validResultType
, validElements
);
1656 /// Creates a new <see cref="DbNewInstanceExpression"/> that produces a row with the specified named columns and the given values, specified as expressions.
1658 /// <param name="columnValues">A list of string-DbExpression key-value pairs that defines the structure and values of the row.</param>
1659 /// <returns>A new DbNewInstanceExpression that represents the construction of the row.</returns>
1660 /// <exception cref="ArgumentNullException"><paramref name="columnValues"/> is null or contains an element with a null column name or expression</exception>
1661 /// <exception cref="ArgumentException">
1662 /// <paramref name="columnValues"/> is empty, or contains a duplicate or invalid column name
1664 public static DbNewInstanceExpression
NewRow(IEnumerable
<KeyValuePair
<string, DbExpression
>> columnValues
)
1666 DbExpressionList validElements
;
1667 TypeUsage resultType
= ArgumentValidation
.ValidateNewRow(columnValues
, out validElements
);
1668 return new DbNewInstanceExpression(resultType
, validElements
);
1672 /// Creates a new <see cref="DbPropertyExpression"/> representing the retrieval of the specified property.
1674 /// <param name="instance">The instance from which to retrieve the property. May be null if the property is static.</param>
1675 /// <param name="propertyMetadata">Metadata for the property to retrieve.</param>
1676 /// <returns>A new DbPropertyExpression representing the property retrieval.</returns>
1677 /// <exception cref="ArgumentNullException"><paramref name="propertyMetadata"/> is null or <paramref name="instance"/> is null and the property is not static.</exception>
1678 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification
= "required for this feature")]
1679 public static DbPropertyExpression
Property(this DbExpression instance
, EdmProperty propertyMetadata
)
1681 return PropertyFromMember(instance
, propertyMetadata
, "propertyMetadata");
1685 /// Creates a new <see cref="DbPropertyExpression"/> representing the retrieval of the specified navigation property.
1687 /// <param name="instance">The instance from which to retrieve the navigation property.</param>
1688 /// <param name="navigationProperty">Metadata for the navigation property to retrieve.</param>
1689 /// <returns>A new DbPropertyExpression representing the navigation property retrieval.</returns>
1690 /// <exception cref="ArgumentNullException"><paramref name="navigationProperty"/> is null or <paramref name="instance"/> is null.</exception>
1691 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification
= "required for this feature")]
1692 public static DbPropertyExpression
Property(this DbExpression instance
, NavigationProperty navigationProperty
)
1694 return PropertyFromMember(instance
, navigationProperty
, "navigationProperty");
1698 /// Creates a new <see cref="DbPropertyExpression"/> representing the retrieval of the specified relationship end member.
1700 /// <param name="instance">The instance from which to retrieve the relationship end member.</param>
1701 /// <param name="relationshipEnd">Metadata for the relationship end member to retrieve.</param>
1702 /// <returns>A new DbPropertyExpression representing the relationship end member retrieval.</returns>
1703 /// <exception cref="ArgumentNullException"><paramref name="relationshipEnd"/> is null or <paramref name="instance"/> is null and the property is not static.</exception>
1704 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification
= "required for this feature")]
1705 public static DbPropertyExpression
Property(this DbExpression instance
, RelationshipEndMember relationshipEnd
)
1707 return PropertyFromMember(instance
, relationshipEnd
, "relationshipEnd");
1711 /// Creates a new <see cref="DbPropertyExpression"/> representing the retrieval of the instance property with the specified name from the given instance.
1713 /// <param name="propertyName">The name of the property to retrieve.</param>
1714 /// <param name="instance">The instance from which to retrieve the property.</param>
1715 /// <returns>A new DbPropertyExpression that represents the property retrieval</returns>
1716 /// <exception cref="ArgumentNullException"><paramref name="propertyName"/> is null or <paramref name="instance"/> is null and the property is not static.</exception>
1717 /// <exception cref="ArgumentOutOfRangeException">No property with the specified name is declared by the type of <paramref name="instance"/>.</exception>
1718 public static DbPropertyExpression
Property(this DbExpression instance
, string propertyName
)
1720 return PropertyByName(instance
, propertyName
, false);
1723 private static DbPropertyExpression
PropertyFromMember(DbExpression instance
, EdmMember property
, string propertyArgumentName
)
1725 TypeUsage resultType
= ArgumentValidation
.ValidateProperty(instance
, property
, propertyArgumentName
);
1726 return new DbPropertyExpression(resultType
, property
, instance
);
1729 private static DbPropertyExpression
PropertyByName(DbExpression instance
, string propertyName
, bool ignoreCase
)
1732 TypeUsage resultType
= ArgumentValidation
.ValidateProperty(instance
, propertyName
, ignoreCase
, out property
);
1733 return new DbPropertyExpression(resultType
, property
, instance
);
1738 #region Lambda-based methods: All, Any, Cross|OuterApply, Cross|FullOuter|Inner|LeftOuterJoin, Filter, GroupBy, Project, Skip, Sort
1740 private static string ExtractAlias(MethodInfo method
)
1742 Debug
.Assert(method
!= null, "Ensure method is non-null before calling ExtractAlias");
1743 string[] aliases
= ExtractAliases(method
);
1744 Debug
.Assert(aliases
.Length
> 0, "Incompatible method: at least one parameter is required");
1748 internal static string[] ExtractAliases(MethodInfo method
)
1750 Debug
.Assert(method
!= null, "Ensure method is non-null before calling ExtractAlias");
1751 ParameterInfo
[] methodParams
= method
.GetParameters();
1754 if (method
.IsStatic
&& typeof(System
.Runtime
.CompilerServices
.Closure
) == methodParams
[0].ParameterType
)
1756 // Static lambda method has additional first closure parameter
1758 paramCount
= methodParams
.Length
- 1;
1762 // Otherwise, method parameters align directly with arguments
1764 paramCount
= methodParams
.Length
;
1767 string[] paramNames
= new string[paramCount
];
1768 bool generateNames
= methodParams
.Skip(start
).Any(p
=> p
.Name
== null);
1769 for (int idx
= start
; idx
< methodParams
.Length
; idx
++)
1771 paramNames
[idx
- start
] = (generateNames
? _bindingAliases
.Next() : methodParams
[idx
].Name
);
1776 private static DbExpressionBinding ConvertToBinding
<TResult
>(DbExpression source
, Func
<DbExpression
, TResult
> argument
, string argumentName
, out TResult argumentResult
)
1778 return ConvertToBinding(source
, "source", argument
, argumentName
, out argumentResult
);
1781 private static DbExpressionBinding ConvertToBinding
<TResult
>(DbExpression source
, string sourceName
, Func
<DbExpression
, TResult
> argument
, string argumentName
, out TResult argumentResult
)
1783 EntityUtil
.CheckArgumentNull(source
, sourceName
);
1784 EntityUtil
.CheckArgumentNull(argument
, argumentName
);
1785 string alias = ExtractAlias(argument
.Method
);
1786 DbExpressionBinding binding
= DbExpressionBuilder
.BindAs(source
, alias);
1787 argumentResult
= argument(binding
.Variable
);
1791 private static DbExpressionBinding
[] ConvertToBinding(DbExpression left
, string leftArgumentName
, DbExpression right
, string rightArgumentName
, Func
<DbExpression
, DbExpression
, DbExpression
> argument
, string argumentName
, out DbExpression argumentExp
)
1793 EntityUtil
.CheckArgumentNull(left
, leftArgumentName
);
1794 EntityUtil
.CheckArgumentNull(right
, rightArgumentName
);
1796 EntityUtil
.CheckArgumentNull(argument
, argumentName
);
1797 string[] aliases
= ExtractAliases(argument
.Method
);
1798 DbExpressionBinding leftBinding
= DbExpressionBuilder
.BindAs(left
, aliases
[0]);
1799 DbExpressionBinding rightBinding
= DbExpressionBuilder
.BindAs(right
, aliases
[1]);
1800 argumentExp
= argument(leftBinding
.Variable
, rightBinding
.Variable
);
1801 return new[] { leftBinding, rightBinding }
;
1804 [MethodImpl(MethodImplOptions
.NoInlining
| MethodImplOptions
.NoOptimization
)]
1805 private static bool TryGetAnonymousTypeValues
<TInstance
, TRequired
>(object instance
, out List
<KeyValuePair
<string, TRequired
>> values
)
1807 Debug
.Assert(instance
!= null, "Ensure instance is non-null before calling TryGetAnonymousTypeValues");
1809 // The following heuristic is used to approximate whether or not TInstance is an anonymous type:
1810 // - Derived directly from System.Object
1811 // - Declares only public instance properties
1812 // - All public instance properties are readable and of an appropriate type
1815 if (typeof(TInstance
).BaseType
.Equals(typeof(object)) &&
1816 typeof(TInstance
).GetProperties(BindingFlags
.Static
).Length
== 0 &&
1817 typeof(TInstance
).GetProperties(BindingFlags
.Instance
| BindingFlags
.NonPublic
).Length
== 0)
1819 List
<KeyValuePair
<string, TRequired
>> foundValues
= null;
1820 foreach (PropertyInfo pi
in typeof(TInstance
).GetProperties(BindingFlags
.Public
| BindingFlags
.Instance
))
1822 if (pi
.CanRead
&& typeof(TRequired
).IsAssignableFrom(pi
.PropertyType
))
1824 if (foundValues
== null)
1826 foundValues
= new List
<KeyValuePair
<string, TRequired
>>();
1828 foundValues
.Add(new KeyValuePair
<string, TRequired
>(pi
.Name
, (TRequired
)pi
.GetValue(instance
, null)));
1836 values
= foundValues
;
1839 return (values
!= null);
1842 private static bool TryResolveToConstant(Type type
, object value, out DbExpression constantOrNullExpression
)
1844 constantOrNullExpression
= null;
1846 Type valueType
= type
;
1847 if (type
.IsGenericType
&& typeof(Nullable
<>).Equals(type
.GetGenericTypeDefinition()))
1849 valueType
= type
.GetGenericArguments()[0];
1852 PrimitiveTypeKind primitiveTypeKind
;
1853 if (ClrProviderManifest
.Instance
.TryGetPrimitiveTypeKind(valueType
, out primitiveTypeKind
))
1855 TypeUsage resultType
= TypeHelpers
.GetLiteralTypeUsage(primitiveTypeKind
);
1858 constantOrNullExpression
= DbExpressionBuilder
.Null(resultType
);
1862 constantOrNullExpression
= DbExpressionBuilder
.Constant(resultType
, value);
1866 return (constantOrNullExpression
!= null);
1869 private static DbExpression ResolveToExpression
<TArgument
>(TArgument argument
)
1871 object untypedArgument
= argument
;
1873 DbExpression constantResult
;
1874 if (TryResolveToConstant(typeof(TArgument
), untypedArgument
, out constantResult
))
1876 return constantResult
;
1879 if (null == untypedArgument
)
1881 return (DbExpression
)null;
1884 // Direct DbExpression result
1885 if (typeof(DbExpression
).IsAssignableFrom(typeof(TArgument
)))
1887 return (DbExpression
)untypedArgument
;
1891 if (typeof(Row
).Equals(typeof(TArgument
)))
1893 return ((Row
)untypedArgument
).ToExpression();
1896 // Conversion from anonymous type instance to DbNewInstanceExpression of a corresponding row type
1897 List
<KeyValuePair
<string, DbExpression
>> columnValues
;
1898 if (TryGetAnonymousTypeValues
<TArgument
, DbExpression
>(untypedArgument
, out columnValues
))
1900 return DbExpressionBuilder
.NewRow(columnValues
);
1903 // The specified instance cannot be resolved to a DbExpression
1904 throw EntityUtil
.NotSupported(Strings
.Cqt_Factory_MethodResultTypeNotSupported(typeof(TArgument
).FullName
));
1907 private static DbApplyExpression
CreateApply(DbExpression source
, Func
<DbExpression
, KeyValuePair
<string, DbExpression
>> apply
, Func
<DbExpressionBinding
, DbExpressionBinding
, DbApplyExpression
> resultBuilder
)
1909 KeyValuePair
<string, DbExpression
> applyTemplate
;
1910 DbExpressionBinding sourceBinding
= ConvertToBinding(source
, apply
, "apply", out applyTemplate
);
1911 DbExpressionBinding applyBinding
= DbExpressionBuilder
.BindAs(applyTemplate
.Value
, applyTemplate
.Key
);
1912 return resultBuilder(sourceBinding
, applyBinding
);
1916 /// Creates a new <see cref="DbQuantifierExpression"/> that determines whether the given predicate holds for all elements of the input set.
1918 /// <param name="source">
1919 /// An expression that specifies the input set.
1921 /// <param name="predicate">
1922 /// A method representing a predicate to evaluate for each member of the input set.
1923 /// This method must produce an expression with a Boolean result type that provides
1924 /// the predicate logic.
1926 /// <returns>A new DbQuantifierExpression that represents the All operation.</returns>
1927 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null</exception>
1928 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="predicate"/> is null</exception>
1929 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
1930 /// <exception cref="ArgumentException">
1931 /// The expression produced by <paramref name="predicate"/> does not have a Boolean result type.
1933 public static DbQuantifierExpression
All(this DbExpression source
, Func
<DbExpression
, DbExpression
> predicate
)
1935 DbExpression predicateExp
;
1936 DbExpressionBinding input
= ConvertToBinding(source
, predicate
, "predicate", out predicateExp
);
1937 return DbExpressionBuilder
.All(input
, predicateExp
);
1941 /// Creates a new <see cref="DbExpression"/> that determines whether the specified set argument is non-empty.
1943 /// <param name="source">An expression that specifies the input set</param>
1944 /// <returns>A new <see cref="DbNotExpression"/> applied to a new <see cref="DbIsEmptyExpression"/> with the specified argument.</returns>
1945 /// <exception cref="ArgumentNullException"><paramref name="source"/> is null</exception>
1946 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
1947 public static DbExpression
Any(this DbExpression source
)
1949 return DbExpressionBuilder
.Exists(source
);
1953 /// Creates a new <see cref="DbExpression"/> that determines whether the specified set argument is non-empty.
1955 /// <param name="argument">An expression that specifies the input set</param>
1956 /// <returns>A new <see cref="DbNotExpression"/> applied to a new <see cref="DbIsEmptyExpression"/> with the specified argument.</returns>
1957 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
1958 /// <exception cref="ArgumentException"><paramref name="argument"/> does not have a collection result type.</exception>
1959 public static DbExpression
Exists(this DbExpression argument
)
1961 return DbExpressionBuilder
.Not(DbExpressionBuilder
.IsEmpty(argument
));
1965 /// Creates a new <see cref="DbQuantifierExpression"/> that determines whether the given predicate holds for any element of the input set.
1967 /// <param name="source">
1968 /// An expression that specifies the input set.
1970 /// <param name="predicate">
1971 /// A method representing the predicate to evaluate for each member of the input set.
1972 /// This method must produce an expression with a Boolean result type that provides
1973 /// the predicate logic.
1975 /// <returns>A new DbQuantifierExpression that represents the Any operation.</returns>
1976 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null</exception>
1977 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="predicate"/> is null</exception>
1978 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
1979 /// <exception cref="ArgumentException">
1980 /// The expression produced by <paramref name="predicate"/> does not have a Boolean result type.
1982 public static DbQuantifierExpression
Any(this DbExpression source
, Func
<DbExpression
, DbExpression
> predicate
)
1984 DbExpression predicateExp
;
1985 DbExpressionBinding input
= ConvertToBinding(source
, predicate
, "predicate", out predicateExp
);
1986 return DbExpressionBuilder
.Any(input
, predicateExp
);
1990 /// Creates a new <see cref="DbApplyExpression"/> that evaluates the given <paramref name="apply"/> expression once for each element of a given input set,
1991 /// producing a collection of rows with corresponding input and apply columns. Rows for which <paramref name="apply"/> evaluates to an empty set are not included.
1993 /// <param name="source">
1994 /// A <see cref="DbExpression"/> that specifies the input set.
1996 /// <param name="apply">
1997 /// A method that specifies the logic to evaluate once for each member of the input set.
1999 /// <returns>An new DbApplyExpression with the specified input and apply bindings and an <see cref="DbExpressionKind"/> of CrossApply.</returns>
2000 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="apply"/> is null</exception>
2001 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2002 /// <exception cref="ArgumentNullException">The result of <paramref name="apply"/> contains a name or expression that is null.</exception>
2003 /// <exception cref="ArgumentException">The result of <paramref name="apply"/> contains a name or expression that is not valid in an expression binding.</exception>
2004 public static DbApplyExpression
CrossApply(this DbExpression source
, Func
<DbExpression
, KeyValuePair
<string, DbExpression
>> apply
)
2006 return CreateApply(source
, apply
, DbExpressionBuilder
.CrossApply
);
2013 /// Creates a new <see cref="DbApplyExpression"/> that evaluates the given <paramref name="apply"/> expression once for each element of a given input set,
2014 /// producing a collection of rows with corresponding input and apply columns. Rows for which <paramref name="apply"/> evaluates to an empty set have an apply column value of <code>null</code>.
2016 /// <param name="source">
2017 /// A <see cref="DbExpression"/> that specifies the input set.
2019 /// <param name="apply">
2020 /// A method that specifies the logic to evaluate once for each member of the input set.
2022 /// <returns>An new DbApplyExpression with the specified input and apply bindings and an <see cref="DbExpressionKind"/> of OuterApply.</returns>
2023 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="apply"/> is null</exception>
2024 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2025 /// <exception cref="ArgumentNullException">The result of <paramref name="apply"/> contains a name or expression that is null.</exception>
2026 /// <exception cref="ArgumentException">The result of <paramref name="apply"/> contains a name or expression that is not valid in an expression binding.</exception>
2027 public static DbApplyExpression
OuterApply(this DbExpression source
, Func
<DbExpression
, KeyValuePair
<string, DbExpression
>> apply
)
2029 return CreateApply(source
, apply
, DbExpressionBuilder
.OuterApply
);
2038 /// Creates a new <see cref="DbJoinExpression"/> that joins the sets specified by the left and right expressions,
2039 /// on the specified join condition, using FullOuterJoin as the <see cref="DbExpressionKind"/>.
2041 /// <param name="left">A <see cref="DbExpression"/> that specifies the left set argument.</param>
2042 /// <param name="right">A <see cref="DbExpression"/> that specifies the right set argument.</param>
2043 /// <param name="joinCondition">
2044 /// A method representing the condition on which to join.
2045 /// This method must produce an expression with a Boolean result type that provides the
2046 /// logic of the join condition.
2049 /// A new DbJoinExpression, with an <see cref="DbExpressionKind"/> of FullOuterJoin, that represents the full outer join operation
2050 /// applied to the left and right input sets under the given join condition.
2052 /// <exception cref="ArgumentNullException">
2053 /// <paramref name="left"/>, <paramref name="right"/> or <paramref name="joinCondition"/> is null.
2055 /// <exception cref="ArgumentException">
2056 /// <paramref name="left"/> or <paramref name="right"/> does not have a collection result type.
2058 /// <exception cref="ArgumentNullException">
2059 /// The expression produced by <paramref name="joinCondition"/> is null.
2061 /// <exception cref="ArgumentException">
2062 /// The expression produced by <paramref name="joinCondition"/> does not have a Boolean result type.
2064 public static DbJoinExpression
FullOuterJoin(this DbExpression left
, DbExpression right
, Func
<DbExpression
, DbExpression
, DbExpression
> joinCondition
)
2066 DbExpression condExp
;
2067 DbExpressionBinding
[] inputs
= ConvertToBinding(left
, "left", right
, "right", joinCondition
, "joinCondition", out condExp
);
2068 return DbExpressionBuilder
.FullOuterJoin(inputs
[0], inputs
[1], condExp
);
2072 /// Creates a new <see cref="DbJoinExpression"/> that joins the sets specified by the left and right expressions,
2073 /// on the specified join condition, using InnerJoin as the <see cref="DbExpressionKind"/>.
2075 /// <param name="left">A <see cref="DbExpression"/> that specifies the left set argument.</param>
2076 /// <param name="right">A <see cref="DbExpression"/> that specifies the right set argument.</param>
2077 /// <param name="joinCondition">
2078 /// A method representing the condition on which to join.
2079 /// This method must produce an expression with a Boolean result type that provides the
2080 /// logic of the join condition.
2083 /// A new DbJoinExpression, with an <see cref="DbExpressionKind"/> of InnerJoin, that represents the inner join operation
2084 /// applied to the left and right input sets under the given join condition.
2086 /// <exception cref="ArgumentNullException">
2087 /// <paramref name="left"/>, <paramref name="right"/> or <paramref name="joinCondition"/> is null.
2089 /// <exception cref="ArgumentException">
2090 /// <paramref name="left"/> or <paramref name="right"/> does not have a collection result type.
2092 /// <exception cref="ArgumentNullException">
2093 /// The expression produced by <paramref name="joinCondition"/> is null.
2095 /// <exception cref="ArgumentException">
2096 /// The expression produced by <paramref name="joinCondition"/> does not have a Boolean result type.
2098 public static DbJoinExpression
InnerJoin(this DbExpression left
, DbExpression right
, Func
<DbExpression
, DbExpression
, DbExpression
> joinCondition
)
2100 DbExpression condExp
;
2101 DbExpressionBinding
[] inputs
= ConvertToBinding(left
, "left", right
, "right", joinCondition
, "joinCondition", out condExp
);
2102 return DbExpressionBuilder
.InnerJoin(inputs
[0], inputs
[1], condExp
);
2106 /// Creates a new <see cref="DbJoinExpression"/> that joins the sets specified by the left and right expressions,
2107 /// on the specified join condition, using LeftOuterJoin as the <see cref="DbExpressionKind"/>.
2109 /// <param name="left">A <see cref="DbExpression"/> that specifies the left set argument.</param>
2110 /// <param name="right">A <see cref="DbExpression"/> that specifies the right set argument.</param>
2111 /// <param name="joinCondition">
2112 /// A method representing the condition on which to join.
2113 /// This method must produce an expression with a Boolean result type that provides the
2114 /// logic of the join condition.
2117 /// A new DbJoinExpression, with an <see cref="DbExpressionKind"/> of LeftOuterJoin, that represents the left outer join operation
2118 /// applied to the left and right input sets under the given join condition.
2120 /// <exception cref="ArgumentNullException">
2121 /// <paramref name="left"/>, <paramref name="right"/> or <paramref name="joinCondition"/> is null.
2123 /// <exception cref="ArgumentException">
2124 /// <paramref name="left"/> or <paramref name="right"/> does not have a collection result type.
2126 /// <exception cref="ArgumentNullException">
2127 /// The expression produced by <paramref name="joinCondition"/> is null.
2129 /// <exception cref="ArgumentException">
2130 /// The expression produced by <paramref name="joinCondition"/> does not have a Boolean result type.
2132 public static DbJoinExpression
LeftOuterJoin(this DbExpression left
, DbExpression right
, Func
<DbExpression
, DbExpression
, DbExpression
> joinCondition
)
2134 DbExpression condExp
;
2135 DbExpressionBinding
[] inputs
= ConvertToBinding(left
, "left", right
, "right", joinCondition
, "joinCondition", out condExp
);
2136 return DbExpressionBuilder
.LeftOuterJoin(inputs
[0], inputs
[1], condExp
);
2140 /// Creates a new <see cref="DbJoinExpression"/> that joins the sets specified by the outer and inner expressions,
2141 /// on an equality condition between the specified outer and inner keys, using InnerJoin as the <see cref="DbExpressionKind"/>.
2143 /// <param name="outer">A <see cref="DbExpression"/> that specifies the outer set argument.</param>
2144 /// <param name="inner">A <see cref="DbExpression"/> that specifies the inner set argument.</param>
2145 /// <param name="outerKey">A method that specifies how the outer key value should be derived from an element of the outer set.</param>
2146 /// <param name="innerKey">A method that specifies how the inner key value should be derived from an element of the inner set.</param>
2148 /// A new DbJoinExpression, with an <see cref="DbExpressionKind"/> of InnerJoin, that represents the inner join operation
2149 /// applied to the left and right input sets under a join condition that compares the outer and inner key values for equality.
2151 /// <exception cref="ArgumentNullException">
2152 /// <paramref name="outer"/>, <paramref name="inner"/>, <paramref name="outerKey"/> or <paramref name="innerKey"/> is null.
2154 /// <exception cref="ArgumentException">
2155 /// <paramref name="outer"/> or <paramref name="inner"/> does not have a collection result type.
2157 /// <exception cref="ArgumentNullException">
2158 /// The expression produced by <paramref name="outerKey"/> or <paramref name="innerKey"/> is null.
2160 /// <exception cref="ArgumentException">
2161 /// The expressions produced by <paramref name="outerKey"/> and <paramref name="innerKey"/> are not comparable for equality.
2163 public static DbJoinExpression
Join(this DbExpression outer
, DbExpression inner
, Func
<DbExpression
, DbExpression
> outerKey
, Func
<DbExpression
, DbExpression
> innerKey
)
2165 DbExpression leftOperand
;
2166 DbExpressionBinding leftBinding
= ConvertToBinding(outer
, "outer", outerKey
, "outerKey", out leftOperand
);
2168 DbExpression rightOperand
;
2169 DbExpressionBinding rightBinding
= ConvertToBinding(inner
, "inner", innerKey
, "innerKey", out rightOperand
);
2171 DbExpression joinCondition
= DbExpressionBuilder
.Equal(leftOperand
, rightOperand
);
2173 return DbExpressionBuilder
.InnerJoin(leftBinding
, rightBinding
, joinCondition
);
2177 /// Creates a new <see cref="DbProjectExpression"/> that projects the specified selector over the sets specified by the outer and inner
2178 /// expressions, joined on an equality condition between the specified outer and inner keys, using InnerJoin as the <see cref="DbExpressionKind"/>.
2180 /// <param name="outer">A <see cref="DbExpression"/> that specifies the outer set argument.</param>
2181 /// <param name="inner">A <see cref="DbExpression"/> that specifies the inner set argument.</param>
2182 /// <param name="outerKey">A method that specifies how the outer key value should be derived from an element of the outer set.</param>
2183 /// <param name="innerKey">A method that specifies how the inner key value should be derived from an element of the inner set.</param>
2184 /// <param name="selector">
2185 /// A method that specifies how an element of the result set should be derived from elements of the inner and outer sets.
2186 /// This method must produce an instance of a type that is compatible with Join and can be resolved
2187 /// into a <see cref="DbExpression"/>.
2188 /// Compatibility requirements for <typeparamref name="TSelector"/> are described in remarks.
2191 /// A new DbProjectExpression with the specified selector as its projection, and a new DbJoinExpression as its input.
2192 /// The input DbJoinExpression is created with an <see cref="DbExpressionKind"/> of InnerJoin, that represents the inner join operation
2193 /// applied to the left and right input sets under a join condition that compares the outer and inner key values for equality.
2195 /// <exception cref="ArgumentNullException">
2196 /// <paramref name="outer"/>, <paramref name="inner"/>, <paramref name="outerKey"/>, <paramref name="innerKey"/> or <paramref name="selector"/> is null.
2198 /// <exception cref="ArgumentException">
2199 /// <paramref name="outer"/> or <paramref name="inner"/> does not have a collection result type.
2201 /// <exception cref="ArgumentNullException">
2202 /// The expression produced by <paramref name="outerKey"/> or <paramref name="innerKey"/> is null.
2204 /// <exception cref="ArgumentNullException">
2205 /// The result of <paramref name="selector"/> is null after conversion to DbExpression.
2207 /// <exception cref="ArgumentException">
2208 /// The expressions produced by <paramref name="outerKey"/> and <paramref name="innerKey"/> are not comparable for equality.
2210 /// <exception cref="ArgumentException">
2211 /// The result of <paramref name="selector"/> is not compatible with SelectMany.
2214 /// To be compatible with Join, <typeparamref name="TSelector"/> must be derived from <see cref="DbExpression"/>,
2215 /// or must be an anonymous type with DbExpression-derived properties.
2217 /// The following are examples of supported types for <typeparamref name="TSelector"/>:
2218 /// <code>outer.Join(inner, o => o.Property("ID"), i => i.Property("ID"), (o, i) => o.Property("Name"))</code> (<typeparamref name="TSelector"/> is <see cref="DbPropertyExpression"/>).
2219 /// <code>outer.Join(inner, o => o.Property("ID"), i => i.Property("ID"), (o, i) => new { OName = o.Property("Name"), IName = i.Property("Name") })</code> (<typeparamref name="TSelector"/> is an anonymous type with DbExpression-derived properties).
2222 public static DbProjectExpression Join
<TSelector
>(this DbExpression outer
, DbExpression inner
, Func
<DbExpression
, DbExpression
> outerKey
, Func
<DbExpression
, DbExpression
> innerKey
, Func
<DbExpression
, DbExpression
, TSelector
> selector
)
2224 // Defer argument validation for all but the selector to the selector-less overload of Join
2225 DbJoinExpression joinExpression
= DbExpressionBuilder
.Join(outer
, inner
, outerKey
, innerKey
);
2227 // Ensure that the selector is non-null;
2228 EntityUtil
.CheckArgumentNull(selector
, "selector");
2230 // Bind the join expression and produce the selector based on the left and right inputs
2231 DbExpressionBinding joinBinding
= DbExpressionBuilder
.Bind(joinExpression
);
2232 DbExpression left
= DbExpressionBuilder
.Property(joinBinding
.Variable
, joinExpression
.Left
.VariableName
);
2233 DbExpression right
= DbExpressionBuilder
.Property(joinBinding
.Variable
, joinExpression
.Right
.VariableName
);
2234 TSelector intermediateSelector
= selector(left
, right
);
2235 DbExpression projection
= DbExpressionBuilder
.ResolveToExpression(intermediateSelector
);
2237 // Project the selector over the join expression and return the resulting DbProjectExpression
2238 return DbExpressionBuilder
.Project(joinBinding
, projection
);
2242 /// Creates a new <see cref="DbSortExpression"/> that sorts the given input set by the specified sort key,
2243 /// with ascending sort order and default collation.
2245 /// <param name="source">An expression that specifies the input set.</param>
2246 /// <param name="sortKey">
2247 /// A method that specifies how to derive the sort key expression given a member of the input set.
2248 /// This method must produce an expression with an order-comparable result type that provides the
2249 /// sort key definition.
2251 /// <returns>A new DbSortExpression that represents the order-by operation.</returns>
2252 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="sortKey"/> is null.</exception>
2253 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="sortKey"/> is null.</exception>
2254 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2255 /// <exception cref="ArgumentException">
2256 /// The expression produced by <paramref name="sortKey"/> does not have an order-comparable result type.
2258 public static DbSortExpression
OrderBy(this DbExpression source
, Func
<DbExpression
, DbExpression
> sortKey
)
2260 DbExpression keyExpression
;
2261 DbExpressionBinding input
= ConvertToBinding(source
, sortKey
, "sortKey", out keyExpression
);
2262 DbSortClause sortClause
= DbExpressionBuilder
.ToSortClause(keyExpression
);
2263 return DbExpressionBuilder
.Sort(input
, new DbSortClause
[] { sortClause }
);
2267 /// Creates a new <see cref="DbSortExpression"/> that sorts the given input set by the specified sort key,
2268 /// with ascending sort order and the specified collation.
2270 /// <param name="source">An expression that specifies the input set.</param>
2271 /// <param name="sortKey">
2272 /// A method that specifies how to derive the sort key expression given a member of the input set.
2273 /// This method must produce an expression with an order-comparable result type that provides the
2274 /// sort key definition.
2276 /// <param name="collation">The collation to sort under</param>
2277 /// <returns>A new DbSortExpression that represents the order-by operation.</returns>
2278 /// <exception cref="ArgumentNullException"><paramref name="source"/>, <paramref name="sortKey"/> or <paramref name="collation"/> is null.</exception>
2279 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="sortKey"/> is null.</exception>
2280 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2281 /// <exception cref="ArgumentException">
2282 /// The expression produced by <paramref name="sortKey"/> does not have an order-comparable string result type.
2284 /// <exception cref="ArgumentOutOfRangeException"><paramref name="collation"/> is empty or contains only space characters</exception>
2285 public static DbSortExpression
OrderBy(this DbExpression source
, Func
<DbExpression
, DbExpression
> sortKey
, string collation
)
2287 DbExpression keyExpression
;
2288 DbExpressionBinding input
= ConvertToBinding(source
, sortKey
, "sortKey", out keyExpression
);
2289 DbSortClause sortClause
= DbExpressionBuilder
.ToSortClause(keyExpression
, collation
);
2290 return DbExpressionBuilder
.Sort(input
, new DbSortClause
[] { sortClause }
);
2294 /// Creates a new <see cref="DbSortExpression"/> that sorts the given input set by the specified sort key,
2295 /// with descending sort order and default collation.
2297 /// <param name="source">An expression that specifies the input set.</param>
2298 /// <param name="sortKey">
2299 /// A method that specifies how to derive the sort key expression given a member of the input set.
2300 /// This method must produce an expression with an order-comparable result type that provides the
2301 /// sort key definition.
2303 /// <returns>A new DbSortExpression that represents the order-by operation.</returns>
2304 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="sortKey"/> is null.</exception>
2305 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="sortKey"/> is null.</exception>
2306 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2307 /// <exception cref="ArgumentException">
2308 /// The expression produced by <paramref name="sortKey"/> does not have an order-comparable result type.
2310 public static DbSortExpression
OrderByDescending(this DbExpression source
, Func
<DbExpression
, DbExpression
> sortKey
)
2312 DbExpression keyExpression
;
2313 DbExpressionBinding input
= ConvertToBinding(source
, sortKey
, "sortKey", out keyExpression
);
2314 DbSortClause sortClause
= DbExpressionBuilder
.ToSortClauseDescending(keyExpression
);
2315 return DbExpressionBuilder
.Sort(input
, new DbSortClause
[] { sortClause }
);
2319 /// Creates a new <see cref="DbSortExpression"/> that sorts the given input set by the specified sort key,
2320 /// with descending sort order and the specified collation.
2322 /// <param name="source">An expression that specifies the input set.</param>
2323 /// <param name="sortKey">
2324 /// A method that specifies how to derive the sort key expression given a member of the input set.
2325 /// This method must produce an expression with an order-comparable result type that provides the
2326 /// sort key definition.
2328 /// <param name="collation">The collation to sort under</param>
2329 /// <returns>A new DbSortExpression that represents the order-by operation.</returns>
2330 /// <exception cref="ArgumentNullException"><paramref name="source"/>, <paramref name="sortKey"/> or <paramref name="collation"/> is null.</exception>
2331 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="sortKey"/> is null.</exception>
2332 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2333 /// <exception cref="ArgumentException">
2334 /// The expression produced by <paramref name="sortKey"/> does not have an order-comparable string result type.
2336 /// <exception cref="ArgumentOutOfRangeException"><paramref name="collation"/> is empty or contains only space characters</exception>
2337 public static DbSortExpression
OrderByDescending(this DbExpression source
, Func
<DbExpression
, DbExpression
> sortKey
, string collation
)
2339 DbExpression keyExpression
;
2340 DbExpressionBinding input
= ConvertToBinding(source
, sortKey
, "sortKey", out keyExpression
);
2341 DbSortClause sortClause
= DbExpressionBuilder
.ToSortClauseDescending(keyExpression
, collation
);
2342 return DbExpressionBuilder
.Sort(input
, new DbSortClause
[] { sortClause }
);
2346 /// Creates a new <see cref="DbProjectExpression"/> that selects the specified expression over the given input set.
2348 /// <param name="source">An expression that specifies the input set.</param>
2349 /// <param name="projection">
2350 /// A method that specifies how to derive the projected expression given a member of the input set.
2351 /// This method must produce an instance of a type that is compatible with Select and can be resolved
2352 /// into a <see cref="DbExpression"/>.
2353 /// Compatibility requirements for <typeparamref name="TProjection"/> are described in remarks.
2355 /// <typeparam name="TProjection">The method result type of <paramref name="projection"/>.</typeparam>
2356 /// <returns>A new DbProjectExpression that represents the select operation.</returns>
2357 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="projection"/> is null</exception>
2358 /// <exception cref="ArgumentNullException">The result of <paramref name="projection"/> is null.</exception>
2360 /// To be compatible with Select, <typeparamref name="TProjection"/> must be derived from <see cref="DbExpression"/>,
2361 /// or must be an anonymous type with DbExpression-derived properties.
2363 /// The following are examples of supported types for <typeparamref name="TProjection"/>:
2364 /// <code>source.Select(x => x.Property("Name"))</code> (<typeparamref name="TProjection"/> is <see cref="DbPropertyExpression"/>).
2365 /// <code>source.Select(x => new { Name = x.Property("Name") })</code> (<typeparamref name="TProjection"/> is an anonymous type with a DbExpression-derived property).
2368 public static DbProjectExpression Select
<TProjection
>(this DbExpression source
, Func
<DbExpression
, TProjection
> projection
)
2370 EntityUtil
.CheckArgumentNull(projection
, "projection");
2371 TProjection intermediateProjection
;
2372 DbExpressionBinding input
= ConvertToBinding(source
, projection
, "projection", out intermediateProjection
);
2373 DbExpression projectionExp
= ResolveToExpression(intermediateProjection
);
2374 return DbExpressionBuilder
.Project(input
, projectionExp
);
2378 /// Creates a new <see cref="DbApplyExpression"/> that evaluates the given <paramref name="apply"/> expression once for each element of a given input set,
2379 /// producing a collection of rows with corresponding input and apply columns. Rows for which <paramref name="apply"/> evaluates to an empty set are not included.
2380 /// A <see cref="DbProjectExpression"/> is then created that selects the <paramref name="apply"/> column from each row, producing the overall collection of <paramref name="apply"/> results.
2382 /// <param name="source">
2383 /// A <see cref="DbExpression"/> that specifies the input set.
2385 /// <param name="apply">
2386 /// A method that represents the logic to evaluate once for each member of the input set.
2388 /// <returns>An new DbProjectExpression that selects the apply column from a new DbApplyExpression with the specified input and apply bindings and an <see cref="DbExpressionKind"/> of CrossApply.</returns>
2389 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="apply"/> is null.</exception>
2390 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="apply"/> is null.</exception>
2391 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2392 /// <exception cref="ArgumentException">The expression produced by <paramref name="apply"/> does not have a collection type.</exception>
2393 public static DbProjectExpression
SelectMany(this DbExpression source
, Func
<DbExpression
, DbExpression
> apply
)
2395 DbExpression functorResult
;
2396 DbExpressionBinding inputBinding
= ConvertToBinding(source
, apply
, "apply", out functorResult
);
2398 DbExpressionBinding functorBinding
= DbExpressionBuilder
.Bind(functorResult
);
2399 DbApplyExpression intermediateApply
= DbExpressionBuilder
.CrossApply(inputBinding
, functorBinding
);
2401 DbExpressionBinding projectionBinding
= DbExpressionBuilder
.Bind(intermediateApply
);
2402 return DbExpressionBuilder
.Project(projectionBinding
, DbExpressionBuilder
.Property(projectionBinding
.Variable
, functorBinding
.VariableName
));
2406 /// Creates a new <see cref="DbApplyExpression"/> that evaluates the given <paramref name="apply"/> expression once for each element of a given input set,
2407 /// producing a collection of rows with corresponding input and apply columns. Rows for which <paramref name="apply"/> evaluates to an empty set are not included.
2408 /// A <see cref="DbProjectExpression"/> is then created that selects the specified <paramref name="selector"/> over each row, producing the overall collection of results.
2410 /// <typeparam name="TSelector">The method result type of <paramref name="selector"/>.</typeparam>
2411 /// <param name="source">
2412 /// A <see cref="DbExpression"/> that specifies the input set.
2414 /// <param name="apply">
2415 /// A method that represents the logic to evaluate once for each member of the input set.
2417 /// <param name="selector">
2418 /// A method that specifies how an element of the result set should be derived given an element of the input and apply sets.
2419 /// This method must produce an instance of a type that is compatible with SelectMany and can be resolved into a <see cref="DbExpression"/>.
2420 /// Compatibility requirements for <typeparamref name="TSelector"/> are described in remarks.
2422 /// <returns>An new DbProjectExpression that selects the result of the given selector from a new DbApplyExpression with the specified input and apply bindings and an <see cref="DbExpressionKind"/> of CrossApply.</returns>
2423 /// <exception cref="ArgumentNullException"><paramref name="source"/>, <paramref name="apply"/> or <paramref name="selector"/> is null.</exception>
2424 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="apply"/> is null.</exception>
2425 /// <exception cref="ArgumentNullException">The result of <paramref name="selector"/> is null on conversion to DbExpression</exception>
2426 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2427 /// <exception cref="ArgumentException">The expression produced by <paramref name="apply"/> does not have a collection type.</exception>
2429 /// To be compatible with SelectMany, <typeparamref name="TSelector"/> must be derived from <see cref="DbExpression"/>,
2430 /// or must be an anonymous type with DbExpression-derived properties.
2432 /// The following are examples of supported types for <typeparamref name="TSelector"/>:
2433 /// <code>source.SelectMany(x => x.Property("RelatedCollection"), (source, apply) => apply.Property("Name"))</code> (<typeparamref name="TSelector"/> is <see cref="DbPropertyExpression"/>).
2434 /// <code>source.SelectMany(x => x.Property("RelatedCollection"), (source, apply) => new { SourceName = source.Property("Name"), RelatedName = apply.Property("Name") })</code> (<typeparamref name="TSelector"/> is an anonymous type with DbExpression-derived properties).
2437 public static DbProjectExpression SelectMany
<TSelector
>(this DbExpression source
, Func
<DbExpression
, DbExpression
> apply
, Func
<DbExpression
, DbExpression
, TSelector
> selector
)
2439 DbExpression functorResult
;
2440 DbExpressionBinding inputBinding
= ConvertToBinding(source
, apply
, "apply", out functorResult
);
2441 EntityUtil
.CheckArgumentNull(selector
, "selector");
2443 DbExpressionBinding functorBinding
= DbExpressionBuilder
.Bind(functorResult
);
2444 DbApplyExpression intermediateApply
= DbExpressionBuilder
.CrossApply(inputBinding
, functorBinding
);
2446 DbExpressionBinding projectionBinding
= DbExpressionBuilder
.Bind(intermediateApply
);
2447 DbExpression left
= DbExpressionBuilder
.Property(projectionBinding
.Variable
, inputBinding
.VariableName
);
2448 DbExpression right
= DbExpressionBuilder
.Property(projectionBinding
.Variable
, functorBinding
.VariableName
);
2449 TSelector selectorResult
= selector(left
, right
);
2450 DbExpression projection
= ResolveToExpression(selectorResult
);
2451 return DbExpressionBuilder
.Project(projectionBinding
, projection
);
2455 /// Creates a new <see cref="DbSkipExpression"/> that skips the specified number of elements from the given sorted input set.
2457 /// <param name="argument">A <see cref="DbSortExpression"/> that specifies the sorted input set.</param>
2458 /// <param name="count">An expression the specifies how many elements of the ordered set to skip.</param>
2459 /// <returns>A new DbSkipExpression that represents the skip operation.</returns>
2460 /// <exception cref="ArgumentNullException">
2461 /// <paramref name="argument"/> or <paramref name="count"/> is null.
2463 /// <exception cref="ArgumentException">
2464 /// <paramref name="count"/> is not <see cref="DbConstantExpression"/> or <see cref="DbParameterReferenceExpression"/> or has a
2465 /// result type that is not equal or promotable to a 64-bit integer type.
2467 public static DbSkipExpression
Skip(this DbSortExpression argument
, DbExpression count
)
2469 EntityUtil
.CheckArgumentNull(argument
, "argument");
2470 return DbExpressionBuilder
.Skip(argument
.Input
, argument
.SortOrder
, count
);
2474 /// Creates a new <see cref="DbLimitExpression"/> that restricts the number of elements in the Argument collection to the specified count Limit value.
2475 /// Tied results are not included in the output.
2477 /// <param name="argument">An expression that specifies the input collection.</param>
2478 /// <param name="count">An expression that specifies the limit value.</param>
2479 /// <returns>A new DbLimitExpression with the specified argument and count limit values that does not include tied results.</returns>
2480 /// <exception cref="ArgumentNullException"><paramref name="argument"/> or <paramref name="count"/> is null</exception>
2481 /// <exception cref="ArgumentException">
2482 /// <paramref name="argument"/> does not have a collection result type,
2483 /// or <paramref name="count"/> does not have a result type that is equal or promotable to a 64-bit integer type.
2485 public static DbLimitExpression
Take(this DbExpression argument
, DbExpression count
)
2487 return DbExpressionBuilder
.Limit(argument
, count
);
2490 private static DbSortExpression
CreateThenBy(DbSortExpression source
, Func
<DbExpression
, DbExpression
> sortKey
, bool ascending, string collation
, bool useCollation
)
2492 EntityUtil
.CheckArgumentNull(source
, "source");
2493 EntityUtil
.CheckArgumentNull(sortKey
, "sortKey");
2494 DbExpression sortKeyResult
= sortKey(source
.Input
.Variable
);
2495 DbSortClause sortClause
;
2498 sortClause
= (ascending ? DbExpressionBuilder
.ToSortClause(sortKeyResult
, collation
) : DbExpressionBuilder
.ToSortClauseDescending(sortKeyResult
, collation
));
2502 sortClause
= (ascending ? DbExpressionBuilder
.ToSortClause(sortKeyResult
) : DbExpressionBuilder
.ToSortClauseDescending(sortKeyResult
));
2505 List
<DbSortClause
> newSortOrder
= new List
<DbSortClause
>(source
.SortOrder
.Count
+ 1);
2506 newSortOrder
.AddRange(source
.SortOrder
);
2507 newSortOrder
.Add(sortClause
);
2509 return DbExpressionBuilder
.Sort(source
.Input
, newSortOrder
);
2513 /// Creates a new <see cref="DbSortExpression"/> that with a sort order that includes the sort order
2514 /// of the given order input set together with the specified sort key in ascending sort order and
2515 /// with default collation.
2517 /// <param name="source">A DbSortExpression that specifies the ordered input set.</param>
2518 /// <param name="sortKey">
2519 /// A method that specifies how to derive the additional sort key expression given a member of the
2521 /// This method must produce an expression with an order-comparable result type that provides the
2522 /// sort key definition.
2524 /// <returns>A new DbSortExpression that represents the new overall order-by operation.</returns>
2525 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="sortKey"/> is null.</exception>
2526 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="sortKey"/> is null.</exception>
2527 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2528 /// <exception cref="ArgumentException">
2529 /// The expression produced by <paramref name="sortKey"/> does not have an order-comparable result type.
2531 public static DbSortExpression
ThenBy(this DbSortExpression source
, Func
<DbExpression
, DbExpression
> sortKey
)
2533 return CreateThenBy(source
, sortKey
, true, null, false);
2537 /// Creates a new <see cref="DbSortExpression"/> that with a sort order that includes the sort order
2538 /// of the given order input set together with the specified sort key in ascending sort order and
2539 /// with the specified collation.
2541 /// <param name="source">A DbSortExpression that specifies the ordered input set.</param>
2542 /// <param name="sortKey">
2543 /// A method that specifies how to derive the additional sort key expression given a member of the
2545 /// This method must produce an expression with an order-comparable result type that provides the
2546 /// sort key definition.
2548 /// <param name="collation">The collation to sort under</param>
2549 /// <returns>A new DbSortExpression that represents the new overall order-by operation.</returns>
2550 /// <exception cref="ArgumentNullException"><paramref name="source"/>, <paramref name="sortKey"/> or <paramref name="collation"/> is null.</exception>
2551 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="sortKey"/> is null.</exception>
2552 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2553 /// <exception cref="ArgumentException">
2554 /// The expression produced by <paramref name="sortKey"/> does not have an order-comparable string result type.
2556 /// <exception cref="ArgumentOutOfRangeException"><paramref name="collation"/> is empty or contains only space characters</exception>
2557 public static DbSortExpression
ThenBy(this DbSortExpression source
, Func
<DbExpression
, DbExpression
> sortKey
, string collation
)
2559 return CreateThenBy(source
, sortKey
, true, collation
, true);
2563 /// Creates a new <see cref="DbSortExpression"/> that with a sort order that includes the sort order
2564 /// of the given order input set together with the specified sort key in descending sort order and
2565 /// with default collation.
2567 /// <param name="source">A DbSortExpression that specifies the ordered input set.</param>
2568 /// <param name="sortKey">
2569 /// A method that specifies how to derive the additional sort key expression given a member of the
2571 /// This method must produce an expression with an order-comparable result type that provides the
2572 /// sort key definition.
2574 /// <returns>A new DbSortExpression that represents the new overall order-by operation.</returns>
2575 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="sortKey"/> is null.</exception>
2576 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="sortKey"/> is null.</exception>
2577 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2578 /// <exception cref="ArgumentException">
2579 /// The expression produced by <paramref name="sortKey"/> does not have an order-comparable result type.
2581 public static DbSortExpression
ThenByDescending(this DbSortExpression source
, Func
<DbExpression
, DbExpression
> sortKey
)
2583 return CreateThenBy(source
, sortKey
, false, null, false);
2587 /// Creates a new <see cref="DbSortExpression"/> that with a sort order that includes the sort order
2588 /// of the given order input set together with the specified sort key in descending sort order and
2589 /// with the specified collation.
2591 /// <param name="source">A DbSortExpression that specifies the ordered input set.</param>
2592 /// <param name="sortKey">
2593 /// A method that specifies how to derive the additional sort key expression given a member of the
2595 /// This method must produce an expression with an order-comparable result type that provides the
2596 /// sort key definition.
2598 /// <param name="collation">The collation to sort under</param>
2599 /// <returns>A new DbSortExpression that represents the new overall order-by operation.</returns>
2600 /// <exception cref="ArgumentNullException"><paramref name="source"/>, <paramref name="sortKey"/> or <paramref name="collation"/> is null.</exception>
2601 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="sortKey"/> is null.</exception>
2602 /// <exception cref="ArgumentException"><paramref name="source"/> does not have a collection result type.</exception>
2603 /// <exception cref="ArgumentException">
2604 /// The expression produced by <paramref name="sortKey"/> does not have an order-comparable string result type.
2606 /// <exception cref="ArgumentOutOfRangeException"><paramref name="collation"/> is empty or contains only space characters</exception>
2607 public static DbSortExpression
ThenByDescending(this DbSortExpression source
, Func
<DbExpression
, DbExpression
> sortKey
, string collation
)
2609 return CreateThenBy(source
, sortKey
, false, collation
, true);
2613 /// Creates a new <see cref="DbFilterExpression"/> that filters the elements in the given input set using the specified predicate.
2615 /// <param name="source">
2616 /// An expression that specifies the input set.
2618 /// <param name="predicate">
2619 /// A method representing the predicate to evaluate for each member of the input set.
2620 /// This method must produce an expression with a Boolean result type that provides
2621 /// the predicate logic.
2623 /// <returns>A new DbQuantifierExpression that represents the Any operation.</returns>
2624 /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null</exception>
2625 /// <exception cref="ArgumentNullException">The expression produced by <paramref name="predicate"/> is null</exception>
2626 /// <exception cref="ArgumentException">
2627 /// The expression produced by <paramref name="predicate"/> does not have a Boolean result type.
2629 public static DbFilterExpression
Where(this DbExpression source
, Func
<DbExpression
, DbExpression
> predicate
)
2631 DbExpression predicateExp
;
2632 DbExpressionBinding input
= ConvertToBinding(source
, predicate
, "predicate", out predicateExp
);
2633 return DbExpressionBuilder
.Filter(input
, predicateExp
);
2637 /// Creates a new <see cref="DbExpression"/> that computes the union of the left and right set arguments with duplicates removed.
2639 /// <param name="left">An expression that defines the left set argument.</param>
2640 /// <param name="right">An expression that defines the right set argument.</param>
2641 /// <returns>A new DbExpression that computes the union, without duplicates, of the the left and right arguments.</returns>
2642 /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null</exception>
2643 /// <exception cref="ArgumentException">No common collection result type with an equality-comparable element type exists between <paramref name="left"/> and <paramref name="right"/>.</exception>
2644 public static DbExpression
Union(this DbExpression left
, DbExpression right
)
2646 return DbExpressionBuilder
.Distinct(DbExpressionBuilder
.UnionAll(left
, right
));
2651 #region Internal Helper API - ideally these methods should be removed
2653 internal static AliasGenerator AliasGenerator
2655 get { return _bindingAliases; }
2658 internal static DbNullExpression
CreatePrimitiveNullExpression(PrimitiveTypeKind primitiveType
)
2660 switch(primitiveType
)
2662 case PrimitiveTypeKind
.Binary
:
2664 case PrimitiveTypeKind
.Boolean
:
2666 case PrimitiveTypeKind
.Byte
:
2668 case PrimitiveTypeKind
.DateTime
:
2669 return _dateTimeNull
;
2670 case PrimitiveTypeKind
.DateTimeOffset
:
2671 return _dateTimeOffsetNull
;
2672 case PrimitiveTypeKind
.Decimal
:
2673 return _decimalNull
;
2674 case PrimitiveTypeKind
.Double
:
2676 case PrimitiveTypeKind
.Geography
:
2677 return _geographyNull
;
2678 case PrimitiveTypeKind
.Geometry
:
2679 return _geometryNull
;
2680 case PrimitiveTypeKind
.Guid
:
2682 case PrimitiveTypeKind
.Int16
:
2684 case PrimitiveTypeKind
.Int32
:
2686 case PrimitiveTypeKind
.Int64
:
2688 case PrimitiveTypeKind
.SByte
:
2690 case PrimitiveTypeKind
.Single
:
2692 case PrimitiveTypeKind
.String
:
2694 case PrimitiveTypeKind
.Time
:
2698 throw EntityUtil
.InvalidEnumerationValue(typeof(PrimitiveTypeKind
), (int)primitiveType
);
2702 internal static DbApplyExpression
CreateApplyExpressionByKind(DbExpressionKind applyKind
, DbExpressionBinding input
, DbExpressionBinding apply
)
2704 Debug
.Assert(DbExpressionKind
.CrossApply
== applyKind
|| DbExpressionKind
.OuterApply
== applyKind
, "Invalid ApplyType");
2708 case DbExpressionKind
.CrossApply
:
2709 return CrossApply(input
, apply
);
2711 case DbExpressionKind
.OuterApply
:
2712 return OuterApply(input
, apply
);
2715 throw EntityUtil
.InvalidEnumerationValue(typeof(DbExpressionKind
), (int)applyKind
);
2719 internal static DbExpression
CreateJoinExpressionByKind(DbExpressionKind joinKind
, DbExpression joinCondition
, DbExpressionBinding input1
, DbExpressionBinding input2
)
2721 Debug
.Assert(DbExpressionKind
.CrossJoin
== joinKind
||
2722 DbExpressionKind
.FullOuterJoin
== joinKind
||
2723 DbExpressionKind
.InnerJoin
== joinKind
||
2724 DbExpressionKind
.LeftOuterJoin
== joinKind
,
2725 "Invalid DbExpressionKind for CreateJoinExpressionByKind");
2727 if (DbExpressionKind
.CrossJoin
== joinKind
)
2729 Debug
.Assert(null == joinCondition
, "Condition should not be specified for CrossJoin");
2730 return CrossJoin(new DbExpressionBinding
[2] { input1, input2 }
);
2734 Debug
.Assert(joinCondition
!= null, "Condition must be specified for non-CrossJoin");
2738 case DbExpressionKind
.InnerJoin
:
2739 return InnerJoin(input1
, input2
, joinCondition
);
2741 case DbExpressionKind
.LeftOuterJoin
:
2742 return LeftOuterJoin(input1
, input2
, joinCondition
);
2744 case DbExpressionKind
.FullOuterJoin
:
2745 return FullOuterJoin(input1
, input2
, joinCondition
);
2748 throw EntityUtil
.InvalidEnumerationValue(typeof(DbExpressionKind
), (int)joinKind
);
2754 /// Used only by span rewriter, when a row could be specified as an argument
2756 internal static DbIsNullExpression
CreateIsNullExpressionAllowingRowTypeArgument(DbExpression argument
)
2758 TypeUsage resultType
= ArgumentValidation
.ValidateIsNull(argument
, true);
2759 return new DbIsNullExpression(resultType
, argument
, true);
2763 /// Creates a new <see cref="DbElementExpression"/> that converts a single-member set with a single property
2764 /// into a singleton. The result type of the created <see cref="DbElementExpression"/> equals the result type
2765 /// of the single property of the element of the argument.
2767 /// This method should only be used when the argument is of a collection type with
2768 /// element of structured type with only one property.
2770 /// <param name="argument">An expression that specifies the input set.</param>
2771 /// <returns>A DbElementExpression that represents the conversion of the single-member set argument to a singleton.</returns>
2772 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
2773 /// <exception cref="ArgumentException">
2774 /// <paramref name="argument"/> is associated with a different command tree,
2775 /// or does not have a collection result type, or its element type is not a structured type
2776 /// with only one property
2778 internal static DbElementExpression
CreateElementExpressionUnwrapSingleProperty(DbExpression argument
)
2780 TypeUsage resultType
= ArgumentValidation
.ValidateElement(argument
);
2782 // Change the result type of the element expression to the type of the
2783 // single property of the element of its operand.
2784 IList
<EdmProperty
> properties
= TypeHelpers
.GetProperties(resultType
);
2785 if (properties
== null || properties
.Count
!= 1)
2787 throw EntityUtil
.Argument(System
.Data
.Entity
.Strings
.Cqt_Element_InvalidArgumentForUnwrapSingleProperty
, "arg");
2789 resultType
= properties
[0].TypeUsage
;
2790 return new DbElementExpression(resultType
, argument
, true);
2794 /// Creates a new <see cref="DbRelatedEntityRef"/> that describes how to satisfy the relationship
2795 /// navigation operation from <paramref name="sourceEnd"/> to <paramref name="targetEnd"/>, which
2796 /// must be declared by the same relationship type.
2797 /// DbRelatedEntityRefs are used in conjuction with <see cref="DbNewInstanceExpression"/>
2798 /// to construct Entity instances that are capable of resolving relationship navigation operations based on
2799 /// the provided DbRelatedEntityRefs without the need for additional navigation operations.
2800 /// Note also that this factory method is not intended to be part of the public Command Tree API
2801 /// since its intent is to support Entity constructors in view definitions that express information about
2802 /// related Entities using the 'WITH RELATIONSHIP' clause in eSQL.
2804 /// <param name="sourceEnd">The relationship end from which navigation takes place</param>
2805 ///<param name="targetEnd">The relationship end to which navigation may be satisifed using the target entity ref</param>
2806 ///<param name="targetEntity">An expression that produces a reference to the target entity (and must therefore have a Ref result type)</param>
2807 internal static DbRelatedEntityRef
CreateRelatedEntityRef(RelationshipEndMember sourceEnd
, RelationshipEndMember targetEnd
, DbExpression targetEntity
)
2809 return new DbRelatedEntityRef(sourceEnd
, targetEnd
, targetEntity
);
2813 /// Creates a new <see cref="DbNewInstanceExpression"/> that constructs an instance of an Entity type
2814 /// together with the specified information about Entities related to the newly constructed Entity by
2815 /// relationship navigations where the target end has multiplicity of at most one.
2816 /// Note that this factory method is not intended to be part of the public Command Tree API since its
2817 /// intent is to support Entity constructors in view definitions that express information about
2818 /// related Entities using the 'WITH RELATIONSHIP' clause in eSQL.
2820 /// <param name="instanceType">The type of the Entity instance that is being constructed</param>
2821 /// <param name="attributeValues">Values for each (non-relationship) property of the Entity</param>
2822 /// <param name="relationships">A (possibly empty) list of <see cref="DbRelatedEntityRef"/>s that describe Entities that are related to the constructed Entity by various relationship types.</param>
2823 /// <returns>A new DbNewInstanceExpression that represents the construction of the Entity, and includes the specified related Entity information in the see <see cref="DbNewInstanceExpression.RelatedEntityReferences"/> collection.</returns>
2824 internal static DbNewInstanceExpression
CreateNewEntityWithRelationshipsExpression(EntityType entityType
, IList
<DbExpression
> attributeValues
, IList
<DbRelatedEntityRef
> relationships
)
2826 DbExpressionList validAttributes
;
2827 System
.Collections
.ObjectModel
.ReadOnlyCollection
<DbRelatedEntityRef
> validRelatedRefs
;
2828 TypeUsage resultType
= ArgumentValidation
.ValidateNewEntityWithRelationships(entityType
, attributeValues
, relationships
, out validAttributes
, out validRelatedRefs
);
2829 return new DbNewInstanceExpression(resultType
, validAttributes
, validRelatedRefs
);
2833 /// Same as <see cref="Navigate(DbExpression, RelationshipEndMember, RelationshipEndMember)"/> only allows the property type of <paramref name="fromEnd"/>
2834 /// to be any type in the same type hierarchy as the result type of <paramref name="navigateFrom"/>.
2835 /// Only used by relationship span.
2837 /// <param name="navigateFrom"></param>
2838 /// <param name="fromEnd"></param>
2839 /// <param name="toEnd"></param>
2840 /// <returns></returns>
2841 internal static DbRelationshipNavigationExpression
NavigateAllowingAllRelationshipsInSameTypeHierarchy(this DbExpression navigateFrom
, RelationshipEndMember fromEnd
, RelationshipEndMember toEnd
)
2843 RelationshipType relType
;
2844 TypeUsage resultType
= ArgumentValidation
.ValidateNavigate(navigateFrom
, fromEnd
, toEnd
, out relType
, allowAllRelationshipsInSameTypeHierarchy
: true);
2845 return new DbRelationshipNavigationExpression(resultType
, relType
, fromEnd
, toEnd
, navigateFrom
);
2848 internal static DbPropertyExpression
CreatePropertyExpressionFromMember(DbExpression instance
, EdmMember member
)
2850 return PropertyFromMember(instance
, member
, "member");
2853 #if ENABLE_NESTAGGREGATE
2855 /// Creates a new <see cref="NestAggregate"/> over the specified argument
2857 /// <param name="argument">The argument over which to perform the nest operation</param>
2858 /// <returns>A new nest aggregate with a reference to the given argument.</returns>
2859 /// <exception cref="ArgumentNullException"><paramref name="argument"/> is null</exception>
2860 /// <exception cref="ArgumentException"><paramref name="argument"/> is associated with a different command tree</exception>
2861 /*CQT_PUBLIC_API(*/internal/*)*/ NestAggregate
CreateNestAggregate(Expression argument
)
2863 return new NestAggregate(this, argument
);
2867 #if METHOD_EXPRESSION
2869 /// Creates a new <see cref="MethodExpression"/> representing the invocation of the specified method on the given instance with the given arguments.
2871 /// <param name="methodInfo">The metadata for the method to invoke.</param>
2872 /// <param name="instance">The invocation target.</param>
2873 /// <param name="args">The arguments to the method.</param>
2874 /// <returns>A new MethodExpression that represents the method invocation.</returns>
2875 /// <exception cref="ArgumentNullException">
2876 /// <paramref name="methodInfo"/> or <paramref name="instance"/> is null,
2877 /// or <paramref name="args"/> is null or contains null
2879 /// <exception cref="ArgumentException">
2880 /// <paramref name="methodInfo"/> is not associated with this command tree's metadata workspace,
2881 /// <paramref name="instance"/> is associated with a different command tree
2882 /// or has a result type that is not equal or promotable to the declaring type of the method,
2883 /// or <paramref name="args"/> contains an incorrect number of expressions,
2884 /// an expression with a result type that is not equal or promotable to the type of the corresponding
2885 /// method parameter, or an expression that is associated with a different command tree.
2887 /*CQT_PUBLIC_API(*/internal/*)*/ MethodExpression
CreateInstanceMethodExpression(MethodMetadata methodInfo
, Expression instance
, IList
<Expression
> args
)
2889 if (methodInfo
!= null && methodInfo
.IsStatic
)
2891 throw EntityUtil
.Argument(System
.Data
.Entity
.Strings
.Cqt_Factory_InstanceMethodRequired
, "methodInfo");
2894 return new MethodExpression(this, methodInfo
, args
, instance
);
2898 /// Creates a new <see cref="MethodExpression"/> representing the invocation of the specified method with the given arguments.
2900 /// <param name="methodInfo">The metadata for the method to invoke.</param>
2901 /// <param name="args">The arguments to the method.</param>
2902 /// <returns>A new MethodExpression that represents the method invocation.</returns>
2903 /// <exception cref="ArgumentNullException"><paramref name="methodInfo"/> is null, or <paramref name="args"/> is null or contains null</exception>
2904 /// <exception cref="ArgumentException">
2905 /// <paramref name="methodInfo"/> is not associated with this command tree's metadata workspace,
2906 /// or <paramref name="args"/> contains an incorrect number of expressions,
2907 /// an expression with a result type that is not equal or promotable to the type of the corresponding
2908 /// method parameter, or an expression that is associated with a different command tree.
2910 /*CQT_PUBLIC_API(*/internal/*)*/ MethodExpression
CreateStaticMethodExpression(MethodMetadata methodInfo
, IList
<Expression
> args
)
2912 if (methodInfo
!= null && !methodInfo
.IsStatic
)
2914 throw EntityUtil
.Argument(System
.Data
.Entity
.Strings
.Cqt_Factory_StaticMethodRequired
, "methodInfo");
2917 return new MethodExpression(this, methodInfo
, args
, null);