|
//---------------------------------------------------------------------
// <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<string, DbExpression> 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<string, DbExpression> 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"); } }
}
}
|