1 //---------------------------------------------------------------------
2 // <copyright file="ValueExpressions.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
8 //---------------------------------------------------------------------
10 namespace System.Data.Common.CommandTrees
13 using System.Collections.Generic;
14 using System.Data.Common;
15 using System.Data.Common.CommandTrees.Internal;
16 using System.Data.Metadata.Edm;
17 using System.Diagnostics;
20 /// Represents a constant value.
22 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
23 public sealed class DbConstantExpression : DbExpression
25 private readonly bool _shouldCloneValue;
26 private readonly object _value;
28 internal DbConstantExpression(TypeUsage resultType, object value)
29 : base(DbExpressionKind.Constant, resultType)
31 Debug.Assert(value != null, "DbConstantExpression value cannot be null");
32 Debug.Assert(TypeSemantics.IsScalarType(resultType), "DbConstantExpression must have a primitive or enum value");
33 Debug.Assert(!value.GetType().IsEnum || TypeSemantics.IsEnumerationType(resultType), "value is an enum while the result type is not of enum type.");
34 Debug.Assert(Helper.AsPrimitive(resultType.EdmType).ClrEquivalentType == (value.GetType().IsEnum ? value.GetType().GetEnumUnderlyingType() : value.GetType()),
35 "the type of the value has to match the result type (for enum types only underlying types are compared).");
37 // binary values should be cloned before use
38 PrimitiveType primitiveType;
39 this._shouldCloneValue = TypeHelpers.TryGetEdmType<PrimitiveType>(resultType, out primitiveType)
40 && primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Binary;
42 if (this._shouldCloneValue)
44 // DevDiv#480416: DbConstantExpression with a binary value is not fully immutable
46 this._value = ((byte[])value).Clone();
55 /// Provides direct access to the constant value, even for byte[] constants.
57 /// <returns>The object value contained by this constant expression, not a copy.</returns>
58 internal object GetValue()
64 /// Gets the constant value.
70 // DevDiv#480416: DbConstantExpression with a binary value is not fully immutable
72 if (this._shouldCloneValue)
74 return ((byte[])_value).Clone();
84 /// The visitor pattern method for expression visitors that do not produce a result value.
86 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
87 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
88 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
91 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
93 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
94 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
95 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
96 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
97 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
103 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
104 public sealed class DbNullExpression : DbExpression
106 internal DbNullExpression(TypeUsage type)
107 : base(DbExpressionKind.Null, type)
112 /// The visitor pattern method for expression visitors that do not produce a result value.
114 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
115 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
116 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
119 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
121 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
122 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
123 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
124 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
125 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
129 /// Represents a reference to a variable that is currently in scope.
131 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
132 public sealed class DbVariableReferenceExpression : DbExpression
134 private readonly string _name;
136 internal DbVariableReferenceExpression(TypeUsage type, string name)
137 : base(DbExpressionKind.VariableReference, type)
139 Debug.Assert(name != null, "DbVariableReferenceExpression Name cannot be null");
145 /// Gets the name of the referenced variable.
147 public string VariableName { get { return _name; } }
150 /// The visitor pattern method for expression visitors that do not produce a result value.
152 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
153 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
154 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
157 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
159 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
160 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
161 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
162 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
163 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
167 /// Represents a reference to a parameter declared on the command tree that contains this expression.
169 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
170 public sealed class DbParameterReferenceExpression : DbExpression
172 private readonly string _name;
174 internal DbParameterReferenceExpression(TypeUsage type, string name)
175 : base(DbExpressionKind.ParameterReference, type)
177 Debug.Assert(DbCommandTree.IsValidParameterName(name), "DbParameterReferenceExpression name should be valid");
183 /// Gets the name of the referenced parameter.
185 public string ParameterName { get { return _name; } }
188 /// The visitor pattern method for expression visitors that do not produce a result value.
190 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
191 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
192 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
195 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
197 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
198 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
199 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
200 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
201 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
205 /// Represents the retrieval of a static or instance property.
207 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
208 public sealed class DbPropertyExpression : DbExpression
210 private readonly EdmMember _property;
211 private readonly DbExpression _instance;
213 internal DbPropertyExpression(TypeUsage resultType, EdmMember property, DbExpression instance)
214 : base(DbExpressionKind.Property, resultType)
216 Debug.Assert(property != null, "DbPropertyExpression property cannot be null");
217 Debug.Assert(instance != null, "DbPropertyExpression instance cannot be null");
218 Debug.Assert(Helper.IsEdmProperty(property) ||
219 Helper.IsRelationshipEndMember(property) ||
220 Helper.IsNavigationProperty(property), "DbExpression property must be a property, navigation property, or relationship end");
222 this._property = property;
223 this._instance = instance;
227 /// Gets the property metadata for the property to retrieve.
229 public EdmMember Property { get { return _property; } }
232 /// Gets the <see cref="DbExpression"/> that defines the instance from which the property should be retrieved.
234 public DbExpression Instance { get { return _instance; } }
237 /// The visitor pattern method for expression visitors that do not produce a result value.
239 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
240 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
241 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
244 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
246 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
247 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
248 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
249 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
250 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
253 /// Creates a new KeyValuePair<string, DbExpression> based on this property expression.
254 /// The string key will be the name of the referenced property, while the DbExpression value will be the property expression itself.
256 /// <returns>A new KeyValuePair<string, DbExpression> with key and value derived from the DbPropertyExpression</returns>
257 public KeyValuePair<string, DbExpression> ToKeyValuePair()
259 return new KeyValuePair<string, DbExpression>(this.Property.Name, this);
262 public static implicit operator KeyValuePair<string, DbExpression>(DbPropertyExpression value)
264 EntityUtil.CheckArgumentNull(value, "value");
265 return value.ToKeyValuePair();
270 /// Represents the invocation of a function.
272 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
273 public sealed class DbFunctionExpression : DbExpression
275 private readonly EdmFunction _functionInfo;
276 private readonly DbExpressionList _arguments;
278 internal DbFunctionExpression(TypeUsage resultType, EdmFunction function, DbExpressionList arguments)
279 : base(DbExpressionKind.Function, resultType)
281 Debug.Assert(function != null, "DbFunctionExpression function cannot be null");
282 Debug.Assert(arguments != null, "DbFunctionExpression arguments cannot be null");
283 Debug.Assert(object.ReferenceEquals(resultType, function.ReturnParameter.TypeUsage), "DbFunctionExpression result type must be function return type");
285 this._functionInfo = function;
286 this._arguments = arguments;
290 /// Gets the metadata for the function to invoke.
292 public EdmFunction Function { get { return _functionInfo; } }
295 /// Gets an <see cref="DbExpression"/> list that provides the arguments to the function.
297 public IList<DbExpression> Arguments { get { return this._arguments; } }
300 /// The visitor pattern method for expression visitors that do not produce a result value.
302 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
303 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
304 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
307 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
309 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
310 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
311 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
312 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
313 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
317 /// Represents the application of a Lambda function.
319 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
320 public sealed class DbLambdaExpression : DbExpression
322 private readonly DbLambda _lambda;
323 private readonly DbExpressionList _arguments;
325 internal DbLambdaExpression(TypeUsage resultType, DbLambda lambda, DbExpressionList args)
326 : base(DbExpressionKind.Lambda, resultType)
328 Debug.Assert(lambda != null, "DbLambdaExpression lambda cannot be null");
329 Debug.Assert(args != null, "DbLambdaExpression arguments cannot be null");
330 Debug.Assert(object.ReferenceEquals(resultType, lambda.Body.ResultType), "DbLambdaExpression result type must be Lambda body result type");
331 Debug.Assert(lambda.Variables.Count == args.Count, "DbLambdaExpression argument count does not match Lambda parameter count");
333 this._lambda = lambda;
334 this._arguments = args;
338 /// Gets the <see cref="DbLambda"/> representing the Lambda function applied by this expression.
340 public DbLambda Lambda { get { return _lambda; } }
343 /// Gets a <see cref="DbExpression"/> list that provides the arguments to which the Lambda function should be applied.
345 public IList<DbExpression> Arguments { get { return this._arguments; } }
348 /// The visitor pattern method for expression visitors that do not produce a result value.
350 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
351 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
352 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
355 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
357 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
358 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
359 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
360 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
361 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
364 #if METHOD_EXPRESSION
366 /// Represents the invocation of a method.
368 public sealed class MethodExpression : Expression
370 MethodMetadata m_methodInfo;
371 IList<Expression> m_args;
372 ExpressionLink m_inst;
374 internal MethodExpression(CommandTree cmdTree, MethodMetadata methodInfo, IList<Expression> args, Expression instance)
375 : base(cmdTree, ExpressionKind.Method)
378 // Ensure that the property metadata is non-null and from the same metadata workspace and dataspace as the command tree.
380 CommandTreeTypeHelper.CheckMember(methodInfo, "method", "methodInfo");
383 // Methods that return void are not allowed
385 if (cmdTree.TypeHelper.IsNullOrNullType(methodInfo.Type))
387 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Method_VoidResultInvalid, "methodInfo");
392 throw EntityUtil.ArgumentNull("args");
395 this.m_inst = new ExpressionLink("Instance", cmdTree);
398 // Validate the instance
400 if (methodInfo.IsStatic)
402 if (instance != null)
404 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Method_InstanceInvalidForStatic, "instance");
409 if (null == instance)
411 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Method_InstanceRequiredForInstance, "instance");
414 this.m_inst.SetExpectedType(methodInfo.DefiningType);
415 this.m_inst.InitializeValue(instance);
419 // Validate the arguments
421 m_args = new ExpressionList("Arguments", cmdTree, methodInfo.Parameters, args);
422 m_methodInfo = methodInfo;
423 this.ResultType = methodInfo.Type;
427 /// Gets the metadata for the method to invoke.
429 public MethodMetadata Method { get { return m_methodInfo; } }
432 /// Gets the expressions that provide the arguments to the method.
434 public IList<Expression> Arguments { get { return m_args; } }
437 /// Gets or sets an <see cref="Expression"/> that defines the instance on which the method should be invoked. Must be null for instance methods.
438 /// For static properties, <code>Instance</code> will always be null, and attempting to set a new value will result
439 /// in <see cref="NotSupportedException"/>.
441 /// <exception cref="ArgumentNullException">The expression is null</exception>
442 /// <exception cref="NotSupportedException">The method is static</exception>
443 /// <exception cref="ArgumentException">
444 /// The expression is not associated with the MethodExpression's command tree,
445 /// or its result type is not equal or promotable to the type that defines the method
447 public Expression Instance
449 get { return m_inst.Expression; }
450 /*CQT_PUBLIC_API(*/internal/*)*/ set
452 if (this.m_methodInfo.IsStatic)
454 throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_Method_InstanceInvalidForStatic);
457 this.m_inst.Expression = value;
462 /// The visitor pattern method for expression visitors that do not produce a result value.
464 /// <param name="visitor">An instance of ExpressionVisitor.</param>
465 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
466 public override void Accept(ExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
469 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
471 /// <param name="visitor">An instance of a typed ExpressionVisitor that produces a result value of type TResultType.</param>
472 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
473 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
474 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
475 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
480 /// Represents the navigation of a (composition or association) relationship given the 'from' role, the 'to' role and an instance of the from role
482 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
483 public sealed class DbRelationshipNavigationExpression : DbExpression
485 private readonly RelationshipType _relation;
486 private readonly RelationshipEndMember _fromRole;
487 private readonly RelationshipEndMember _toRole;
488 private readonly DbExpression _from;
490 internal DbRelationshipNavigationExpression(
491 TypeUsage resultType,
492 RelationshipType relType,
493 RelationshipEndMember fromEnd,
494 RelationshipEndMember toEnd,
495 DbExpression navigateFrom)
496 : base(DbExpressionKind.RelationshipNavigation, resultType)
498 Debug.Assert(relType != null, "DbRelationshipNavigationExpression relationship type cannot be null");
499 Debug.Assert(fromEnd != null, "DbRelationshipNavigationExpression 'from' end cannot be null");
500 Debug.Assert(toEnd != null, "DbRelationshipNavigationExpression 'to' end cannot be null");
501 Debug.Assert(navigateFrom != null, "DbRelationshipNavigationExpression navigation source cannot be null");
503 this._relation = relType;
504 this._fromRole = fromEnd;
505 this._toRole = toEnd;
506 this._from = navigateFrom;
510 /// Gets the metadata for the relationship over which navigation occurs
512 public RelationshipType Relationship { get { return _relation; } }
515 /// Gets the metadata for the relationship end to navigate from
517 public RelationshipEndMember NavigateFrom { get { return _fromRole; } }
520 /// Gets the metadata for the relationship end to navigate to
522 public RelationshipEndMember NavigateTo { get { return _toRole; } }
525 /// Gets the <see cref="DbExpression"/> that specifies the instance of the 'from' relationship end from which navigation should occur.
527 public DbExpression NavigationSource { get { return _from; } }
530 /// The visitor pattern method for expression visitors that do not produce a result value.
532 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
533 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
534 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
537 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
539 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
540 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
541 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
542 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
543 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
547 /// Encapsulates the result (represented as a Ref to the resulting Entity) of navigating from
548 /// the specified source end of a relationship to the specified target end. This class is intended
549 /// for use only with <see cref="DbNewInstanceExpression"/>, where an 'owning' instance of that class
550 /// represents the source Entity involved in the relationship navigation.
551 /// Instances of DbRelatedEntityRef may be specified when creating a <see cref="DbNewInstanceExpression"/> that
552 /// constructs an Entity, allowing information about Entities that are related to the newly constructed Entity to be captured.
554 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
555 internal sealed class DbRelatedEntityRef
557 private readonly RelationshipEndMember _sourceEnd;
558 private readonly RelationshipEndMember _targetEnd;
559 private readonly DbExpression _targetEntityRef;
561 internal DbRelatedEntityRef(RelationshipEndMember sourceEnd, RelationshipEndMember targetEnd, DbExpression targetEntityRef)
563 // Validate that the specified relationship ends are:
565 // 2. From the same metadata workspace as that used by the command tree
566 EntityUtil.CheckArgumentNull(sourceEnd, "sourceEnd");
567 EntityUtil.CheckArgumentNull(targetEnd, "targetEnd");
569 // Validate that the specified target entity ref is:
571 EntityUtil.CheckArgumentNull(targetEntityRef, "targetEntityRef");
573 // Validate that the specified source and target ends are:
574 // 1. Declared by the same relationship type
575 if (!object.ReferenceEquals(sourceEnd.DeclaringType, targetEnd.DeclaringType))
577 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEndFromDifferentRelationship, "targetEnd");
579 // 2. Not the same end
580 if (object.ReferenceEquals(sourceEnd, targetEnd))
582 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEndSameAsSourceEnd, "targetEnd");
585 // Validate that the specified target end has multiplicity of at most one
586 if (targetEnd.RelationshipMultiplicity != RelationshipMultiplicity.One &&
587 targetEnd.RelationshipMultiplicity != RelationshipMultiplicity.ZeroOrOne)
589 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEndMustBeAtMostOne, "targetEnd");
592 // Validate that the specified target entity ref actually has a ref result type
593 if (!TypeSemantics.IsReferenceType(targetEntityRef.ResultType))
595 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEntityNotRef, "targetEntityRef");
598 // Validate that the specified target entity is of a type that can be reached by navigating to the specified relationship end
599 EntityTypeBase endType = TypeHelpers.GetEdmType<RefType>(targetEnd.TypeUsage).ElementType;
600 EntityTypeBase targetType = TypeHelpers.GetEdmType<RefType>(targetEntityRef.ResultType).ElementType;
602 if (!endType.EdmEquals(targetType) && !TypeSemantics.IsSubTypeOf(targetType, endType))
604 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEntityNotCompatible, "targetEntityRef");
607 // Validation succeeded, initialize state
608 _targetEntityRef = targetEntityRef;
609 _targetEnd = targetEnd;
610 _sourceEnd = sourceEnd;
614 /// Retrieves the 'source' end of the relationship navigation satisfied by this related entity Ref
616 internal RelationshipEndMember SourceEnd { get { return _sourceEnd; } }
619 /// Retrieves the 'target' end of the relationship navigation satisfied by this related entity Ref
621 internal RelationshipEndMember TargetEnd { get { return _targetEnd; } }
624 /// Retrieves the entity Ref that is the result of navigating from the source to the target end of this related entity Ref
626 internal DbExpression TargetEntityReference { get { return _targetEntityRef; } }
630 /// Represents the construction of a new instance of a given type, including set and record types.
632 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
633 public sealed class DbNewInstanceExpression : DbExpression
635 private readonly DbExpressionList _elements;
636 private readonly System.Collections.ObjectModel.ReadOnlyCollection<DbRelatedEntityRef> _relatedEntityRefs;
638 internal DbNewInstanceExpression(TypeUsage type, DbExpressionList args)
639 : base(DbExpressionKind.NewInstance, type)
641 Debug.Assert(args != null, "DbNewInstanceExpression arguments cannot be null");
642 Debug.Assert(args.Count > 0 || TypeSemantics.IsCollectionType(type), "DbNewInstanceExpression requires at least one argument when not creating an empty collection");
644 this._elements = args;
647 internal DbNewInstanceExpression(TypeUsage resultType, DbExpressionList attributeValues, System.Collections.ObjectModel.ReadOnlyCollection<DbRelatedEntityRef> relationships)
648 : this(resultType, attributeValues)
650 Debug.Assert(TypeSemantics.IsEntityType(resultType), "An entity type is required to create a NewEntityWithRelationships expression");
651 Debug.Assert(relationships != null, "Related entity ref collection cannot be null");
653 this._relatedEntityRefs = (relationships.Count > 0 ? relationships : null);
657 /// Gets an <see cref="DbExpression"/> list that provides the property/column values or set elements for the new instance.
659 public IList<DbExpression> Arguments { get { return _elements; } }
662 /// The visitor pattern method for expression visitors that do not produce a result value.
664 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
665 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
666 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
669 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
671 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
672 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
673 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
674 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
675 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
678 internal bool HasRelatedEntityReferences { get { return (_relatedEntityRefs != null); } }
681 /// Gets the related entity references (if any) for an entity constructor.
682 /// May be null if no related entities were specified - use the <see cref="HasRelatedEntityReferences"/> property to determine this.
684 internal System.Collections.ObjectModel.ReadOnlyCollection<DbRelatedEntityRef> RelatedEntityReferences { get { return _relatedEntityRefs; } }
688 /// Represents a (strongly typed) reference to a specific instance within a given entity set.
690 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
691 public sealed class DbRefExpression : DbUnaryExpression
693 private readonly EntitySet _entitySet;
695 internal DbRefExpression(TypeUsage refResultType, EntitySet entitySet, DbExpression refKeys)
696 : base(DbExpressionKind.Ref, refResultType, refKeys)
698 Debug.Assert(TypeSemantics.IsReferenceType(refResultType), "DbRefExpression requires a reference result type");
700 this._entitySet = entitySet;
704 /// Gets the metadata for the entity set that contains the instance.
706 public EntitySet EntitySet { get { return _entitySet; } }
709 /// The visitor pattern method for expression visitors that do not produce a result value.
711 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
712 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
713 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
716 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
718 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
719 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
720 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
721 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
722 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
726 /// Represents the retrieval of a given entity using the specified Ref.
728 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Deref"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
729 public sealed class DbDerefExpression : DbUnaryExpression
731 internal DbDerefExpression(TypeUsage entityResultType, DbExpression refExpr)
732 : base(DbExpressionKind.Deref, entityResultType, refExpr)
734 Debug.Assert(TypeSemantics.IsEntityType(entityResultType), "DbDerefExpression requires an entity result type");
738 /// The visitor pattern method for expression visitors that do not produce a result value.
740 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
741 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
742 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
745 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
747 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
748 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
749 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
750 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
751 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
755 /// Represents a 'scan' of all elements of a given entity set.
757 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
758 public sealed class DbScanExpression : DbExpression
760 private readonly EntitySetBase _targetSet;
762 internal DbScanExpression(TypeUsage collectionOfEntityType, EntitySetBase entitySet)
763 : base(DbExpressionKind.Scan, collectionOfEntityType)
765 Debug.Assert(entitySet != null, "DbScanExpression entity set cannot be null");
767 this._targetSet = entitySet;
771 /// Gets the metadata for the referenced entity or relationship set.
773 public EntitySetBase Target { get { return _targetSet; } }
776 /// The visitor pattern method for expression visitors that do not produce a result value.
778 /// <param name="visitor">An instance of DbExpressionVisitor.</param>
779 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
780 public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
783 /// The visitor pattern method for expression visitors that produce a result value of a specific type.
785 /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
786 /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
787 /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
788 /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
789 public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }