Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Common / CommandTrees / ValueExpressions.cs
1 //---------------------------------------------------------------------
2 // <copyright file="ValueExpressions.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner  [....]
7 // @backupOwner [....]
8 //---------------------------------------------------------------------
9
10 namespace System.Data.Common.CommandTrees
11 {
12     using System;
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;
18
19     /// <summary>
20     /// Represents a constant value.
21     /// </summary>
22     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
23     public sealed class DbConstantExpression : DbExpression
24     {
25         private readonly bool _shouldCloneValue;
26         private readonly object _value;
27
28         internal DbConstantExpression(TypeUsage resultType, object value)
29             : base(DbExpressionKind.Constant, resultType)
30         {
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).");
36
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;
41
42             if (this._shouldCloneValue)
43             {
44                 // DevDiv#480416: DbConstantExpression with a binary value is not fully immutable
45                 // 
46                 this._value = ((byte[])value).Clone();
47             }
48             else
49             {
50                 this._value = value;
51             }
52         }
53
54         /// <summary>
55         /// Provides direct access to the constant value, even for byte[] constants.
56         /// </summary>
57         /// <returns>The object value contained by this constant expression, not a copy.</returns>
58         internal object GetValue()
59         {
60             return this._value;
61         }
62
63         /// <summary>
64         /// Gets the constant value.
65         /// </summary>
66         public object Value
67         {
68             get
69             {
70                 // DevDiv#480416: DbConstantExpression with a binary value is not fully immutable
71                 // 
72                 if (this._shouldCloneValue)
73                 {
74                     return ((byte[])_value).Clone();
75                 }
76                 else
77                 {
78                     return _value;
79                 }
80             }
81         }
82
83         /// <summary>
84         /// The visitor pattern method for expression visitors that do not produce a result value.
85         /// </summary>
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"); } }
89
90         /// <summary>
91         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
92         /// </summary>
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"); } }
98     }
99
100     /// <summary>
101     /// Represents null.
102     /// </summary>
103     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
104     public sealed class DbNullExpression : DbExpression
105     {
106         internal DbNullExpression(TypeUsage type)
107             : base(DbExpressionKind.Null, type)
108         {
109         }
110
111         /// <summary>
112         /// The visitor pattern method for expression visitors that do not produce a result value.
113         /// </summary>
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"); } }
117
118         /// <summary>
119         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
120         /// </summary>
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"); } }
126     }
127
128     /// <summary>
129     /// Represents a reference to a variable that is currently in scope.
130     /// </summary>
131     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
132     public sealed class DbVariableReferenceExpression : DbExpression
133     {
134         private readonly string _name;
135
136         internal DbVariableReferenceExpression(TypeUsage type, string name)
137             : base(DbExpressionKind.VariableReference, type)
138         {
139             Debug.Assert(name != null, "DbVariableReferenceExpression Name cannot be null");
140             
141             this._name = name;
142         }
143
144         /// <summary>
145         /// Gets the name of the referenced variable.
146         /// </summary>
147         public string VariableName { get { return _name; } }
148
149         /// <summary>
150         /// The visitor pattern method for expression visitors that do not produce a result value.
151         /// </summary>
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"); } }
155
156         /// <summary>
157         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
158         /// </summary>
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"); } }
164     }
165
166     /// <summary>
167     /// Represents a reference to a parameter declared on the command tree that contains this expression.
168     /// </summary>
169     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
170     public sealed class DbParameterReferenceExpression : DbExpression
171     {
172         private readonly string _name;
173
174         internal DbParameterReferenceExpression(TypeUsage type, string name)
175             : base(DbExpressionKind.ParameterReference, type)
176         {
177             Debug.Assert(DbCommandTree.IsValidParameterName(name), "DbParameterReferenceExpression name should be valid");
178
179             this._name = name;
180         }
181
182         /// <summary>
183         /// Gets the name of the referenced parameter.
184         /// </summary>
185         public string ParameterName { get { return _name; } }
186
187         /// <summary>
188         /// The visitor pattern method for expression visitors that do not produce a result value.
189         /// </summary>
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"); } }
193
194         /// <summary>
195         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
196         /// </summary>
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"); } }
202     }
203
204     /// <summary>
205     /// Represents the retrieval of a static or instance property.
206     /// </summary>
207     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
208     public sealed class DbPropertyExpression : DbExpression
209     {
210         private readonly EdmMember _property;
211         private readonly DbExpression _instance;
212
213         internal DbPropertyExpression(TypeUsage resultType, EdmMember property, DbExpression instance)
214             : base(DbExpressionKind.Property, resultType)
215         {
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");
221
222             this._property = property;
223             this._instance = instance;
224         }
225         
226         /// <summary>
227         /// Gets the property metadata for the property to retrieve.
228         /// </summary>
229         public EdmMember Property { get { return _property; } }
230         
231         /// <summary>
232         /// Gets the <see cref="DbExpression"/> that defines the instance from which the property should be retrieved.
233         /// </summary>
234         public DbExpression Instance { get { return _instance; } }
235         
236         /// <summary>
237         /// The visitor pattern method for expression visitors that do not produce a result value.
238         /// </summary>
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"); } }
242
243         /// <summary>
244         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
245         /// </summary>
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"); } }
251
252         /// <summary>
253         /// Creates a new KeyValuePair&lt;string, DbExpression&gt; 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.
255         /// </summary>
256         /// <returns>A new KeyValuePair&lt;string, DbExpression&gt; with key and value derived from the DbPropertyExpression</returns>
257         public KeyValuePair<string, DbExpression> ToKeyValuePair()
258         {
259             return new KeyValuePair<string, DbExpression>(this.Property.Name, this);
260         }
261
262         public static implicit operator KeyValuePair<string, DbExpression>(DbPropertyExpression value)
263         {
264             EntityUtil.CheckArgumentNull(value, "value");
265             return value.ToKeyValuePair();
266         }
267     }
268
269     /// <summary>
270     /// Represents the invocation of a function.
271     /// </summary>
272     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
273     public sealed class DbFunctionExpression : DbExpression
274     {
275         private readonly EdmFunction _functionInfo;
276         private readonly DbExpressionList _arguments;
277
278         internal DbFunctionExpression(TypeUsage resultType, EdmFunction function, DbExpressionList arguments)
279             : base(DbExpressionKind.Function, resultType)
280         {
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");
284
285             this._functionInfo = function;
286             this._arguments = arguments;
287         }
288
289         /// <summary>
290         /// Gets the metadata for the function to invoke.
291         /// </summary>
292         public EdmFunction Function { get { return _functionInfo; } }
293
294         /// <summary>
295         /// Gets an <see cref="DbExpression"/> list that provides the arguments to the function.
296         /// </summary>
297         public IList<DbExpression> Arguments { get { return this._arguments; } }
298
299         /// <summary>
300         /// The visitor pattern method for expression visitors that do not produce a result value.
301         /// </summary>
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"); } }
305
306         /// <summary>
307         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
308         /// </summary>
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"); } }
314     }
315
316     /// <summary>
317     /// Represents the application of a Lambda function.
318     /// </summary>
319     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
320     public sealed class DbLambdaExpression : DbExpression
321     {
322         private readonly DbLambda _lambda;
323         private readonly DbExpressionList _arguments;
324
325         internal DbLambdaExpression(TypeUsage resultType, DbLambda lambda, DbExpressionList args)
326             : base(DbExpressionKind.Lambda, resultType)
327         {
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");
332
333             this._lambda = lambda;
334             this._arguments = args;
335         }
336
337         /// <summary>
338         /// Gets the <see cref="DbLambda"/> representing the Lambda function applied by this expression.
339         /// </summary>
340         public DbLambda Lambda { get { return _lambda; } }
341
342         /// <summary>
343         /// Gets a <see cref="DbExpression"/> list that provides the arguments to which the Lambda function should be applied.
344         /// </summary>
345         public IList<DbExpression> Arguments { get { return this._arguments; } }
346
347         /// <summary>
348         /// The visitor pattern method for expression visitors that do not produce a result value.
349         /// </summary>
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"); } }
353
354         /// <summary>
355         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
356         /// </summary>
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"); } }
362     }
363
364 #if METHOD_EXPRESSION
365     /// <summary>
366     /// Represents the invocation of a method.
367     /// </summary>
368     public sealed class MethodExpression : Expression
369     {
370         MethodMetadata m_methodInfo;
371         IList<Expression> m_args;
372         ExpressionLink m_inst;
373
374         internal MethodExpression(CommandTree cmdTree, MethodMetadata methodInfo, IList<Expression> args, Expression instance)
375             : base(cmdTree, ExpressionKind.Method)
376         {
377             //
378             // Ensure that the property metadata is non-null and from the same metadata workspace and dataspace as the command tree.
379             //
380             CommandTreeTypeHelper.CheckMember(methodInfo, "method", "methodInfo");
381
382             //
383             // Methods that return void are not allowed
384             //
385             if (cmdTree.TypeHelper.IsNullOrNullType(methodInfo.Type))
386             {
387                 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Method_VoidResultInvalid, "methodInfo");
388             }
389
390             if (null == args)
391             {
392                 throw EntityUtil.ArgumentNull("args");
393             }
394
395             this.m_inst = new ExpressionLink("Instance", cmdTree);
396             
397             //
398             // Validate the instance
399             //
400             if (methodInfo.IsStatic)
401             {
402                 if (instance != null)
403                 {
404                     throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Method_InstanceInvalidForStatic, "instance");
405                 }
406             }
407             else
408             {
409                 if (null == instance)
410                 {
411                     throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Method_InstanceRequiredForInstance, "instance");
412                 }
413
414                 this.m_inst.SetExpectedType(methodInfo.DefiningType);
415                 this.m_inst.InitializeValue(instance);
416             }
417
418             //
419             // Validate the arguments
420             //
421             m_args = new ExpressionList("Arguments", cmdTree, methodInfo.Parameters, args);
422             m_methodInfo = methodInfo;
423             this.ResultType = methodInfo.Type;
424         }
425
426         /// <summary>
427         /// Gets the metadata for the method to invoke.
428         /// </summary>
429         public MethodMetadata Method { get { return m_methodInfo; } }
430
431         /// <summary>
432         /// Gets the expressions that provide the arguments to the method.
433         /// </summary>
434         public IList<Expression> Arguments { get { return m_args; } }
435         
436         /// <summary>
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"/>.
440         /// </summary>
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
446         /// </exception>
447         public Expression Instance
448         { 
449             get { return m_inst.Expression; }
450             /*CQT_PUBLIC_API(*/internal/*)*/ set
451             {
452                 if (this.m_methodInfo.IsStatic)
453                 {
454                     throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_Method_InstanceInvalidForStatic);
455                 }
456
457                 this.m_inst.Expression = value; 
458             }
459         }
460         
461         /// <summary>
462         /// The visitor pattern method for expression visitors that do not produce a result value.
463         /// </summary>
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"); } }
467
468         /// <summary>
469         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
470         /// </summary>
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"); } }
476     }
477 #endif
478
479     /// <summary>
480     /// Represents the navigation of a (composition or association) relationship given the 'from' role, the 'to' role and an instance of the from role
481     /// </summary>
482     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
483     public sealed class DbRelationshipNavigationExpression : DbExpression
484     {
485         private readonly RelationshipType _relation;
486         private readonly RelationshipEndMember _fromRole;
487         private readonly RelationshipEndMember _toRole;
488         private readonly DbExpression _from;
489
490         internal DbRelationshipNavigationExpression(
491             TypeUsage resultType,
492             RelationshipType relType,
493             RelationshipEndMember fromEnd,
494             RelationshipEndMember toEnd,
495             DbExpression navigateFrom)
496             : base(DbExpressionKind.RelationshipNavigation, resultType)
497         {
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");
502                         
503             this._relation = relType;
504             this._fromRole = fromEnd;
505             this._toRole = toEnd;
506             this._from = navigateFrom;
507         }
508                 
509         /// <summary>
510         /// Gets the metadata for the relationship over which navigation occurs
511         /// </summary>
512         public RelationshipType Relationship { get { return _relation; } }
513
514         /// <summary>
515         /// Gets the metadata for the relationship end to navigate from
516         /// </summary>
517         public RelationshipEndMember NavigateFrom { get { return _fromRole; } }
518
519         /// <summary>
520         /// Gets the metadata for the relationship end to navigate to
521         /// </summary>
522         public RelationshipEndMember NavigateTo { get { return _toRole; } }
523
524         /// <summary>
525         /// Gets the <see cref="DbExpression"/> that specifies the instance of the 'from' relationship end from which navigation should occur.
526         /// </summary>
527         public DbExpression NavigationSource { get { return _from; } }
528
529         /// <summary>
530         /// The visitor pattern method for expression visitors that do not produce a result value.
531         /// </summary>
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"); } }
535
536         /// <summary>
537         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
538         /// </summary>
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"); } }       
544     }
545
546     /// <summary>
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.
553     /// </summary>
554     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
555     internal sealed class DbRelatedEntityRef
556     {
557         private readonly RelationshipEndMember _sourceEnd;
558         private readonly RelationshipEndMember _targetEnd;
559         private readonly DbExpression _targetEntityRef;
560
561         internal DbRelatedEntityRef(RelationshipEndMember sourceEnd, RelationshipEndMember targetEnd, DbExpression targetEntityRef)
562         {
563             // Validate that the specified relationship ends are:
564             // 1. Non-null
565             // 2. From the same metadata workspace as that used by the command tree
566             EntityUtil.CheckArgumentNull(sourceEnd, "sourceEnd");
567             EntityUtil.CheckArgumentNull(targetEnd, "targetEnd");
568
569             // Validate that the specified target entity ref is:
570             // 1. Non-null
571             EntityUtil.CheckArgumentNull(targetEntityRef, "targetEntityRef");
572                         
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))
576             {
577                 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEndFromDifferentRelationship, "targetEnd");
578             }
579             // 2. Not the same end
580             if (object.ReferenceEquals(sourceEnd, targetEnd))
581             {
582                 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEndSameAsSourceEnd, "targetEnd");
583             }
584
585             // Validate that the specified target end has multiplicity of at most one
586             if (targetEnd.RelationshipMultiplicity != RelationshipMultiplicity.One &&
587                 targetEnd.RelationshipMultiplicity != RelationshipMultiplicity.ZeroOrOne)
588             {
589                 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEndMustBeAtMostOne, "targetEnd");
590             }
591             
592             // Validate that the specified target entity ref actually has a ref result type
593             if (!TypeSemantics.IsReferenceType(targetEntityRef.ResultType))
594             {
595                 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEntityNotRef, "targetEntityRef");
596             }
597
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;
601             // 
602             if (!endType.EdmEquals(targetType) && !TypeSemantics.IsSubTypeOf(targetType, endType))
603             {
604                 throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEntityNotCompatible, "targetEntityRef");
605             }
606             
607             // Validation succeeded, initialize state
608             _targetEntityRef = targetEntityRef;
609             _targetEnd = targetEnd;
610             _sourceEnd = sourceEnd;
611         }
612
613         /// <summary>
614         /// Retrieves the 'source' end of the relationship navigation satisfied by this related entity Ref
615         /// </summary>
616         internal RelationshipEndMember SourceEnd { get { return _sourceEnd; } }
617
618         /// <summary>
619         /// Retrieves the 'target' end of the relationship navigation satisfied by this related entity Ref
620         /// </summary>
621         internal RelationshipEndMember TargetEnd { get { return _targetEnd; } }
622
623         /// <summary>
624         /// Retrieves the entity Ref that is the result of navigating from the source to the target end of this related entity Ref
625         /// </summary>
626         internal DbExpression TargetEntityReference { get { return _targetEntityRef; } }
627     }
628
629     /// <summary>
630     /// Represents the construction of a new instance of a given type, including set and record types.
631     /// </summary>
632     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
633     public sealed class DbNewInstanceExpression : DbExpression
634     {
635         private readonly DbExpressionList _elements;
636         private readonly System.Collections.ObjectModel.ReadOnlyCollection<DbRelatedEntityRef> _relatedEntityRefs;
637
638         internal DbNewInstanceExpression(TypeUsage type, DbExpressionList args)
639             : base(DbExpressionKind.NewInstance, type) 
640         {
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");
643
644             this._elements = args;
645         }
646
647         internal DbNewInstanceExpression(TypeUsage resultType, DbExpressionList attributeValues, System.Collections.ObjectModel.ReadOnlyCollection<DbRelatedEntityRef> relationships)
648             : this(resultType, attributeValues)
649         {
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");
652
653             this._relatedEntityRefs = (relationships.Count > 0 ? relationships : null);
654         }
655
656         /// <summary>
657         /// Gets an <see cref="DbExpression"/> list that provides the property/column values or set elements for the new instance.
658         /// </summary>
659         public IList<DbExpression> Arguments { get { return _elements; } }
660
661         /// <summary>
662         /// The visitor pattern method for expression visitors that do not produce a result value.
663         /// </summary>
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"); } }
667
668         /// <summary>
669         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
670         /// </summary>
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"); } }
676
677
678         internal bool HasRelatedEntityReferences { get { return (_relatedEntityRefs != null); } }
679         
680         /// <summary>
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.
683         /// </summary>
684         internal System.Collections.ObjectModel.ReadOnlyCollection<DbRelatedEntityRef> RelatedEntityReferences { get { return _relatedEntityRefs; } }
685     }
686
687     /// <summary>
688     /// Represents a (strongly typed) reference to a specific instance within a given entity set.
689     /// </summary>
690     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
691     public sealed class DbRefExpression : DbUnaryExpression
692     {
693         private readonly EntitySet _entitySet;
694
695         internal DbRefExpression(TypeUsage refResultType, EntitySet entitySet, DbExpression refKeys)
696             : base(DbExpressionKind.Ref, refResultType, refKeys)
697         {
698             Debug.Assert(TypeSemantics.IsReferenceType(refResultType), "DbRefExpression requires a reference result type");
699
700             this._entitySet = entitySet;
701         }
702
703         /// <summary>
704         /// Gets the metadata for the entity set that contains the instance.
705         /// </summary>
706         public EntitySet EntitySet { get { return _entitySet; } }
707         
708         /// <summary>
709         /// The visitor pattern method for expression visitors that do not produce a result value.
710         /// </summary>
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"); } }
714
715         /// <summary>
716         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
717         /// </summary>
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"); } }
723     }
724
725     /// <summary>
726     /// Represents the retrieval of a given entity using the specified Ref.
727     /// </summary>
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
730     {
731         internal DbDerefExpression(TypeUsage entityResultType, DbExpression refExpr)
732             : base(DbExpressionKind.Deref, entityResultType, refExpr)
733         {
734             Debug.Assert(TypeSemantics.IsEntityType(entityResultType), "DbDerefExpression requires an entity result type");
735         }
736
737         /// <summary>
738         /// The visitor pattern method for expression visitors that do not produce a result value.
739         /// </summary>
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"); } }
743
744         /// <summary>
745         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
746         /// </summary>
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"); } }
752     }
753
754     /// <summary>
755     /// Represents a 'scan' of all elements of a given entity set.
756     /// </summary>
757     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
758     public sealed class DbScanExpression : DbExpression
759     {
760         private readonly EntitySetBase _targetSet;
761
762         internal DbScanExpression(TypeUsage collectionOfEntityType, EntitySetBase entitySet)
763             : base(DbExpressionKind.Scan, collectionOfEntityType)
764         {
765             Debug.Assert(entitySet != null, "DbScanExpression entity set cannot be null");
766             
767             this._targetSet = entitySet;
768         }
769
770         /// <summary>
771         /// Gets the metadata for the referenced entity or relationship set.
772         /// </summary>
773         public EntitySetBase Target { get { return _targetSet; } }
774
775         /// <summary>
776         /// The visitor pattern method for expression visitors that do not produce a result value.
777         /// </summary>
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"); } }
781
782         /// <summary>
783         /// The visitor pattern method for expression visitors that produce a result value of a specific type.
784         /// </summary>
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"); } }
790     }
791 }