File: System\Data\Common\CommandTrees\ValueExpressions.cs
Project: ndp\fx\src\DataEntity\System.Data.Entity.csproj (System.Data.Entity)
//---------------------------------------------------------------------
// <copyright file="ValueExpressions.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner  Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
 
namespace System.Data.Common.CommandTrees
{
    using System;
    using System.Collections.Generic;
    using System.Data.Common;
    using System.Data.Common.CommandTrees.Internal;
    using System.Data.Metadata.Edm;
    using System.Diagnostics;
 
    /// <summary>
    /// Represents a constant value.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbConstantExpression : DbExpression
    {
        private readonly bool _shouldCloneValue;
        private readonly object _value;
 
        internal DbConstantExpression(TypeUsage resultType, object value)
            : base(DbExpressionKind.Constant, resultType)
        {
            Debug.Assert(value != null, "DbConstantExpression value cannot be null");
            Debug.Assert(TypeSemantics.IsScalarType(resultType), "DbConstantExpression must have a primitive or enum value");
            Debug.Assert(!value.GetType().IsEnum || TypeSemantics.IsEnumerationType(resultType), "value is an enum while the result type is not of enum type.");
            Debug.Assert(Helper.AsPrimitive(resultType.EdmType).ClrEquivalentType == (value.GetType().IsEnum ? value.GetType().GetEnumUnderlyingType() : value.GetType()), 
                "the type of the value has to match the result type (for enum types only underlying types are compared).");
 
            // binary values should be cloned before use
            PrimitiveType primitiveType;
            this._shouldCloneValue = TypeHelpers.TryGetEdmType<PrimitiveType>(resultType, out primitiveType)
                && primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Binary;
 
            if (this._shouldCloneValue)
            {
                // DevDiv#480416: DbConstantExpression with a binary value is not fully immutable
                // 
                this._value = ((byte[])value).Clone();
            }
            else
            {
                this._value = value;
            }
        }
 
        /// <summary>
        /// Provides direct access to the constant value, even for byte[] constants.
        /// </summary>
        /// <returns>The object value contained by this constant expression, not a copy.</returns>
        internal object GetValue()
        {
            return this._value;
        }
 
        /// <summary>
        /// Gets the constant value.
        /// </summary>
        public object Value
        {
            get
            {
                // DevDiv#480416: DbConstantExpression with a binary value is not fully immutable
                // 
                if (this._shouldCloneValue)
                {
                    return ((byte[])_value).Clone();
                }
                else
                {
                    return _value;
                }
            }
        }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
 
    /// <summary>
    /// Represents null.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbNullExpression : DbExpression
    {
        internal DbNullExpression(TypeUsage type)
            : base(DbExpressionKind.Null, type)
        {
        }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
 
    /// <summary>
    /// Represents a reference to a variable that is currently in scope.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbVariableReferenceExpression : DbExpression
    {
        private readonly string _name;
 
        internal DbVariableReferenceExpression(TypeUsage type, string name)
            : base(DbExpressionKind.VariableReference, type)
        {
            Debug.Assert(name != null, "DbVariableReferenceExpression Name cannot be null");
            
            this._name = name;
        }
 
        /// <summary>
        /// Gets the name of the referenced variable.
        /// </summary>
        public string VariableName { get { return _name; } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
 
    /// <summary>
    /// Represents a reference to a parameter declared on the command tree that contains this expression.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbParameterReferenceExpression : DbExpression
    {
        private readonly string _name;
 
        internal DbParameterReferenceExpression(TypeUsage type, string name)
            : base(DbExpressionKind.ParameterReference, type)
        {
            Debug.Assert(DbCommandTree.IsValidParameterName(name), "DbParameterReferenceExpression name should be valid");
 
            this._name = name;
        }
 
        /// <summary>
        /// Gets the name of the referenced parameter.
        /// </summary>
        public string ParameterName { get { return _name; } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
 
    /// <summary>
    /// Represents the retrieval of a static or instance property.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbPropertyExpression : DbExpression
    {
        private readonly EdmMember _property;
        private readonly DbExpression _instance;
 
        internal DbPropertyExpression(TypeUsage resultType, EdmMember property, DbExpression instance)
            : base(DbExpressionKind.Property, resultType)
        {
            Debug.Assert(property != null, "DbPropertyExpression property cannot be null");
            Debug.Assert(instance != null, "DbPropertyExpression instance cannot be null");
            Debug.Assert(Helper.IsEdmProperty(property) ||
                         Helper.IsRelationshipEndMember(property) ||
                         Helper.IsNavigationProperty(property), "DbExpression property must be a property, navigation property, or relationship end");
 
            this._property = property;
            this._instance = instance;
        }
        
        /// <summary>
        /// Gets the property metadata for the property to retrieve.
        /// </summary>
        public EdmMember Property { get { return _property; } }
        
        /// <summary>
        /// Gets the <see cref="DbExpression"/> that defines the instance from which the property should be retrieved.
        /// </summary>
        public DbExpression Instance { get { return _instance; } }
        
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// Creates a new KeyValuePair&lt;string, DbExpression&gt; based on this property expression.
        /// The string key will be the name of the referenced property, while the DbExpression value will be the property expression itself.
        /// </summary>
        /// <returns>A new KeyValuePair&lt;string, DbExpression&gt; with key and value derived from the DbPropertyExpression</returns>
        public KeyValuePair<string, DbExpression> ToKeyValuePair()
        {
            return new KeyValuePair<string, DbExpression>(this.Property.Name, this);
        }
 
        public static implicit operator KeyValuePair<string, DbExpression>(DbPropertyExpression value)
        {
            EntityUtil.CheckArgumentNull(value, "value");
            return value.ToKeyValuePair();
        }
    }
 
    /// <summary>
    /// Represents the invocation of a function.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbFunctionExpression : DbExpression
    {
        private readonly EdmFunction _functionInfo;
        private readonly DbExpressionList _arguments;
 
        internal DbFunctionExpression(TypeUsage resultType, EdmFunction function, DbExpressionList arguments)
            : base(DbExpressionKind.Function, resultType)
        {
            Debug.Assert(function != null, "DbFunctionExpression function cannot be null");
            Debug.Assert(arguments != null, "DbFunctionExpression arguments cannot be null");
            Debug.Assert(object.ReferenceEquals(resultType, function.ReturnParameter.TypeUsage), "DbFunctionExpression result type must be function return type");
 
            this._functionInfo = function;
            this._arguments = arguments;
        }
 
        /// <summary>
        /// Gets the metadata for the function to invoke.
        /// </summary>
        public EdmFunction Function { get { return _functionInfo; } }
 
        /// <summary>
        /// Gets an <see cref="DbExpression"/> list that provides the arguments to the function.
        /// </summary>
        public IList<DbExpression> Arguments { get { return this._arguments; } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
 
    /// <summary>
    /// Represents the application of a Lambda function.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbLambdaExpression : DbExpression
    {
        private readonly DbLambda _lambda;
        private readonly DbExpressionList _arguments;
 
        internal DbLambdaExpression(TypeUsage resultType, DbLambda lambda, DbExpressionList args)
            : base(DbExpressionKind.Lambda, resultType)
        {
            Debug.Assert(lambda != null, "DbLambdaExpression lambda cannot be null");
            Debug.Assert(args != null, "DbLambdaExpression arguments cannot be null");
            Debug.Assert(object.ReferenceEquals(resultType, lambda.Body.ResultType), "DbLambdaExpression result type must be Lambda body result type");
            Debug.Assert(lambda.Variables.Count == args.Count, "DbLambdaExpression argument count does not match Lambda parameter count");
 
            this._lambda = lambda;
            this._arguments = args;
        }
 
        /// <summary>
        /// Gets the <see cref="DbLambda"/> representing the Lambda function applied by this expression.
        /// </summary>
        public DbLambda Lambda { get { return _lambda; } }
 
        /// <summary>
        /// Gets a <see cref="DbExpression"/> list that provides the arguments to which the Lambda function should be applied.
        /// </summary>
        public IList<DbExpression> Arguments { get { return this._arguments; } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
 
#if METHOD_EXPRESSION
    /// <summary>
    /// Represents the invocation of a method.
    /// </summary>
    public sealed class MethodExpression : Expression
    {
        MethodMetadata m_methodInfo;
        IList<Expression> m_args;
        ExpressionLink m_inst;
 
        internal MethodExpression(CommandTree cmdTree, MethodMetadata methodInfo, IList<Expression> args, Expression instance)
            : base(cmdTree, ExpressionKind.Method)
        {
            //
            // Ensure that the property metadata is non-null and from the same metadata workspace and dataspace as the command tree.
            //
            CommandTreeTypeHelper.CheckMember(methodInfo, "method", "methodInfo");
 
            //
            // Methods that return void are not allowed
            //
            if (cmdTree.TypeHelper.IsNullOrNullType(methodInfo.Type))
            {
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Method_VoidResultInvalid, "methodInfo");
            }
 
            if (null == args)
            {
                throw EntityUtil.ArgumentNull("args");
            }
 
            this.m_inst = new ExpressionLink("Instance", cmdTree);
            
            //
            // Validate the instance
            //
            if (methodInfo.IsStatic)
            {
                if (instance != null)
                {
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Method_InstanceInvalidForStatic, "instance");
                }
            }
            else
            {
                if (null == instance)
                {
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Method_InstanceRequiredForInstance, "instance");
                }
 
                this.m_inst.SetExpectedType(methodInfo.DefiningType);
                this.m_inst.InitializeValue(instance);
            }
 
            //
            // Validate the arguments
            //
            m_args = new ExpressionList("Arguments", cmdTree, methodInfo.Parameters, args);
            m_methodInfo = methodInfo;
            this.ResultType = methodInfo.Type;
        }
 
        /// <summary>
        /// Gets the metadata for the method to invoke.
        /// </summary>
        public MethodMetadata Method { get { return m_methodInfo; } }
 
        /// <summary>
        /// Gets the expressions that provide the arguments to the method.
        /// </summary>
        public IList<Expression> Arguments { get { return m_args; } }
        
        /// <summary>
        /// Gets or sets an <see cref="Expression"/> that defines the instance on which the method should be invoked. Must be null for instance methods.
        /// For static properties, <code>Instance</code> will always be null, and attempting to set a new value will result
        /// in <see cref="NotSupportedException"/>.
        /// </summary>
        /// <exception cref="ArgumentNullException">The expression is null</exception>
        /// <exception cref="NotSupportedException">The method is static</exception>
        /// <exception cref="ArgumentException">
        ///     The expression is not associated with the MethodExpression's command tree,
        ///     or its result type is not equal or promotable to the type that defines the method
        /// </exception>
        public Expression Instance
        { 
            get { return m_inst.Expression; }
            /*CQT_PUBLIC_API(*/internal/*)*/ set
            {
                if (this.m_methodInfo.IsStatic)
                {
                    throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_Method_InstanceInvalidForStatic);
                }
 
                this.m_inst.Expression = value; 
            }
        }
        
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of ExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(ExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed ExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
#endif
 
    /// <summary>
    /// Represents the navigation of a (composition or association) relationship given the 'from' role, the 'to' role and an instance of the from role
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbRelationshipNavigationExpression : DbExpression
    {
        private readonly RelationshipType _relation;
        private readonly RelationshipEndMember _fromRole;
        private readonly RelationshipEndMember _toRole;
        private readonly DbExpression _from;
 
        internal DbRelationshipNavigationExpression(
            TypeUsage resultType,
            RelationshipType relType,
            RelationshipEndMember fromEnd,
            RelationshipEndMember toEnd,
            DbExpression navigateFrom)
            : base(DbExpressionKind.RelationshipNavigation, resultType)
        {
            Debug.Assert(relType != null, "DbRelationshipNavigationExpression relationship type cannot be null");
            Debug.Assert(fromEnd != null, "DbRelationshipNavigationExpression 'from' end cannot be null");
            Debug.Assert(toEnd != null, "DbRelationshipNavigationExpression 'to' end cannot be null");
            Debug.Assert(navigateFrom != null, "DbRelationshipNavigationExpression navigation source cannot be null");
                        
            this._relation = relType;
            this._fromRole = fromEnd;
            this._toRole = toEnd;
            this._from = navigateFrom;
        }
                
        /// <summary>
        /// Gets the metadata for the relationship over which navigation occurs
        /// </summary>
        public RelationshipType Relationship { get { return _relation; } }
 
        /// <summary>
        /// Gets the metadata for the relationship end to navigate from
        /// </summary>
        public RelationshipEndMember NavigateFrom { get { return _fromRole; } }
 
        /// <summary>
        /// Gets the metadata for the relationship end to navigate to
        /// </summary>
        public RelationshipEndMember NavigateTo { get { return _toRole; } }
 
        /// <summary>
        /// Gets the <see cref="DbExpression"/> that specifies the instance of the 'from' relationship end from which navigation should occur.
        /// </summary>
        public DbExpression NavigationSource { get { return _from; } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }       
    }
 
    /// <summary>
    /// Encapsulates the result (represented as a Ref to the resulting Entity) of navigating from
    /// the specified source end of a relationship to the specified target end. This class is intended
    /// for use only with <see cref="DbNewInstanceExpression"/>, where an 'owning' instance of that class
    /// represents the source Entity involved in the relationship navigation.
    /// Instances of DbRelatedEntityRef may be specified when creating a <see cref="DbNewInstanceExpression"/> that
    /// constructs an Entity, allowing information about Entities that are related to the newly constructed Entity to be captured.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    internal sealed class DbRelatedEntityRef
    {
        private readonly RelationshipEndMember _sourceEnd;
        private readonly RelationshipEndMember _targetEnd;
        private readonly DbExpression _targetEntityRef;
 
        internal DbRelatedEntityRef(RelationshipEndMember sourceEnd, RelationshipEndMember targetEnd, DbExpression targetEntityRef)
        {
            // Validate that the specified relationship ends are:
            // 1. Non-null
            // 2. From the same metadata workspace as that used by the command tree
            EntityUtil.CheckArgumentNull(sourceEnd, "sourceEnd");
            EntityUtil.CheckArgumentNull(targetEnd, "targetEnd");
 
            // Validate that the specified target entity ref is:
            // 1. Non-null
            EntityUtil.CheckArgumentNull(targetEntityRef, "targetEntityRef");
                        
            // Validate that the specified source and target ends are:
            // 1. Declared by the same relationship type
            if (!object.ReferenceEquals(sourceEnd.DeclaringType, targetEnd.DeclaringType))
            {
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEndFromDifferentRelationship, "targetEnd");
            }
            // 2. Not the same end
            if (object.ReferenceEquals(sourceEnd, targetEnd))
            {
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEndSameAsSourceEnd, "targetEnd");
            }
 
            // Validate that the specified target end has multiplicity of at most one
            if (targetEnd.RelationshipMultiplicity != RelationshipMultiplicity.One &&
                targetEnd.RelationshipMultiplicity != RelationshipMultiplicity.ZeroOrOne)
            {
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEndMustBeAtMostOne, "targetEnd");
            }
            
            // Validate that the specified target entity ref actually has a ref result type
            if (!TypeSemantics.IsReferenceType(targetEntityRef.ResultType))
            {
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEntityNotRef, "targetEntityRef");
            }
 
            // Validate that the specified target entity is of a type that can be reached by navigating to the specified relationship end
            EntityTypeBase endType = TypeHelpers.GetEdmType<RefType>(targetEnd.TypeUsage).ElementType;
            EntityTypeBase targetType = TypeHelpers.GetEdmType<RefType>(targetEntityRef.ResultType).ElementType;
            // 
            if (!endType.EdmEquals(targetType) && !TypeSemantics.IsSubTypeOf(targetType, endType))
            {
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelatedEntityRef_TargetEntityNotCompatible, "targetEntityRef");
            }
            
            // Validation succeeded, initialize state
            _targetEntityRef = targetEntityRef;
            _targetEnd = targetEnd;
            _sourceEnd = sourceEnd;
        }
 
        /// <summary>
        /// Retrieves the 'source' end of the relationship navigation satisfied by this related entity Ref
        /// </summary>
        internal RelationshipEndMember SourceEnd { get { return _sourceEnd; } }
 
        /// <summary>
        /// Retrieves the 'target' end of the relationship navigation satisfied by this related entity Ref
        /// </summary>
        internal RelationshipEndMember TargetEnd { get { return _targetEnd; } }
 
        /// <summary>
        /// Retrieves the entity Ref that is the result of navigating from the source to the target end of this related entity Ref
        /// </summary>
        internal DbExpression TargetEntityReference { get { return _targetEntityRef; } }
    }
 
    /// <summary>
    /// Represents the construction of a new instance of a given type, including set and record types.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbNewInstanceExpression : DbExpression
    {
        private readonly DbExpressionList _elements;
        private readonly System.Collections.ObjectModel.ReadOnlyCollection<DbRelatedEntityRef> _relatedEntityRefs;
 
        internal DbNewInstanceExpression(TypeUsage type, DbExpressionList args)
            : base(DbExpressionKind.NewInstance, type) 
        {
            Debug.Assert(args != null, "DbNewInstanceExpression arguments cannot be null");
            Debug.Assert(args.Count > 0 || TypeSemantics.IsCollectionType(type), "DbNewInstanceExpression requires at least one argument when not creating an empty collection");
 
            this._elements = args;
        }
 
        internal DbNewInstanceExpression(TypeUsage resultType, DbExpressionList attributeValues, System.Collections.ObjectModel.ReadOnlyCollection<DbRelatedEntityRef> relationships)
            : this(resultType, attributeValues)
        {
            Debug.Assert(TypeSemantics.IsEntityType(resultType), "An entity type is required to create a NewEntityWithRelationships expression");
            Debug.Assert(relationships != null, "Related entity ref collection cannot be null");
 
            this._relatedEntityRefs = (relationships.Count > 0 ? relationships : null);
        }
 
        /// <summary>
        /// Gets an <see cref="DbExpression"/> list that provides the property/column values or set elements for the new instance.
        /// </summary>
        public IList<DbExpression> Arguments { get { return _elements; } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
 
        internal bool HasRelatedEntityReferences { get { return (_relatedEntityRefs != null); } }
        
        /// <summary>
        /// Gets the related entity references (if any) for an entity constructor. 
        /// May be null if no related entities were specified - use the <see cref="HasRelatedEntityReferences"/> property to determine this.
        /// </summary>
        internal System.Collections.ObjectModel.ReadOnlyCollection<DbRelatedEntityRef> RelatedEntityReferences { get { return _relatedEntityRefs; } }
    }
 
    /// <summary>
    /// Represents a (strongly typed) reference to a specific instance within a given entity set.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbRefExpression : DbUnaryExpression
    {
        private readonly EntitySet _entitySet;
 
        internal DbRefExpression(TypeUsage refResultType, EntitySet entitySet, DbExpression refKeys)
            : base(DbExpressionKind.Ref, refResultType, refKeys)
        {
            Debug.Assert(TypeSemantics.IsReferenceType(refResultType), "DbRefExpression requires a reference result type");
 
            this._entitySet = entitySet;
        }
 
        /// <summary>
        /// Gets the metadata for the entity set that contains the instance.
        /// </summary>
        public EntitySet EntitySet { get { return _entitySet; } }
        
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
 
    /// <summary>
    /// Represents the retrieval of a given entity using the specified Ref.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Deref"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbDerefExpression : DbUnaryExpression
    {
        internal DbDerefExpression(TypeUsage entityResultType, DbExpression refExpr)
            : base(DbExpressionKind.Deref, entityResultType, refExpr)
        {
            Debug.Assert(TypeSemantics.IsEntityType(entityResultType), "DbDerefExpression requires an entity result type");
        }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
 
    /// <summary>
    /// Represents a 'scan' of all elements of a given entity set.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
    public sealed class DbScanExpression : DbExpression
    {
        private readonly EntitySetBase _targetSet;
 
        internal DbScanExpression(TypeUsage collectionOfEntityType, EntitySetBase entitySet)
            : base(DbExpressionKind.Scan, collectionOfEntityType)
        {
            Debug.Assert(entitySet != null, "DbScanExpression entity set cannot be null");
            
            this._targetSet = entitySet;
        }
 
        /// <summary>
        /// Gets the metadata for the referenced entity or relationship set.
        /// </summary>
        public EntitySetBase Target { get { return _targetSet; } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that do not produce a result value.
        /// </summary>
        /// <param name="visitor">An instance of DbExpressionVisitor.</param>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
 
        /// <summary>
        /// The visitor pattern method for expression visitors that produce a result value of a specific type.
        /// </summary>
        /// <param name="visitor">An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.</param>
        /// <typeparam name="TResultType">The type of the result produced by <paramref name="visitor"/></typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="visitor"/> is null</exception>
        /// <returns>An instance of <typeparamref name="TResultType"/>.</returns>
        public override TResultType Accept<TResultType>(DbExpressionVisitor<TResultType> visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
    }
}