Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Common / CommandTrees / ValueExpressions.cs / 1 / ValueExpressions.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees.Internal;
namespace System.Data.Common.CommandTrees
{
///
/// Represents a constant value.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbConstantExpression : DbExpression
{
private object _value;
internal DbConstantExpression(DbCommandTree commandTree, object value)
: base(commandTree, DbExpressionKind.Constant)
{
if (null == value)
{
throw EntityUtil.ArgumentNull("value");
}
//
// Check that typeof(value) is actually a valid constant (i.e. primitive) type
//
PrimitiveTypeKind primitiveTypeKind;
if (!CommandTreeUtils.TryGetPrimtiveTypeKind(value.GetType(), out primitiveTypeKind))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Constant_InvalidType, "value");
}
TypeUsage typeMeta = TypeHelpers.GetLiteralTypeUsage(primitiveTypeKind);
//
// Set the value
//
_value = value;
this.ResultType = typeMeta;
}
internal DbConstantExpression(DbCommandTree commandTree, object value, TypeUsage constantType)
: base(commandTree, DbExpressionKind.Constant)
{
//
// Basic validation of constant value and constant type (non-null, read-only, etc)
//
EntityUtil.CheckArgumentNull(value, "value");
commandTree.TypeHelper.CheckType(constantType, "constantType");
//
// Verify that constantType is a primitive type and that value is an instance of that primitive type
// Note that the value is not validated against applicable facets (such as MaxLength for a string value),
// this is left to the server.
//
PrimitiveType primitiveType;
if (!TypeHelpers.TryGetEdmType(constantType, out primitiveType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Constant_InvalidConstantType(constantType.ToString()), "constantType");
}
PrimitiveTypeKind valueKind;
if (!CommandTreeUtils.TryGetPrimtiveTypeKind(value.GetType(), out valueKind) ||
primitiveType.PrimitiveTypeKind != valueKind)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Constant_InvalidValueForType(constantType.ToString()), "value");
}
//
// Set the value
//
_value = value;
this.ResultType = constantType;
}
///
/// Gets the constant value.
///
public object Value { get { return _value; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents null.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbNullExpression : DbExpression
{
internal DbNullExpression(DbCommandTree commandTree, TypeUsage type)
: base(commandTree, DbExpressionKind.Null)
{
commandTree.TypeHelper.CheckType(type);
this.ResultType = type;
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents a reference to a variable that is currently in scope.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbVariableReferenceExpression : DbExpression
{
private string _name;
internal DbVariableReferenceExpression(DbCommandTree cmdTree, TypeUsage type, string name)
: base(cmdTree, DbExpressionKind.VariableReference)
{
if (string.IsNullOrEmpty(name))
{
throw EntityUtil.ArgumentNull("name");
}
//
// Verify the type of the reference. NullType is not allowed in Var or Parameter references.
//
cmdTree.TypeHelper.CheckType(type);
_name = name;
this.ResultType = type;
}
///
/// Gets the name of the referenced variable.
///
public string VariableName { get { return _name; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents a reference to a parameter declared on the command tree that contains this expression.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbParameterReferenceExpression : DbExpression
{
private string _name;
internal DbParameterReferenceExpression(DbCommandTree cmdTree, TypeUsage type, string name)
: base(cmdTree, DbExpressionKind.ParameterReference)
{
EntityUtil.CheckArgumentNull(name, "name");
// DbCommandTree.CreateParameterRefExpression should check that a parameter with the given name exists,
// and DbCommandTree.AddParameter should have already verified that the name is valid, so this need only
// be asserted here.
Debug.Assert(DbCommandTree.IsValidParameterName(name), string.Format(CultureInfo.InvariantCulture, "Invalid parameter name passed to DbParameterReferenceExpression constructor: '{0}'", name));
//
// Verify the type of the reference. NullType is not allowed in Var or Parameter references.
//
cmdTree.TypeHelper.CheckType(type);
_name = name;
this.ResultType = type;
}
///
/// Gets the name of the referenced parameter.
///
public string ParameterName { get { return _name; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents the retrieval of a static or instance property.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbPropertyExpression : DbExpression
{
private EdmMember _property;
private ExpressionLink _instance;
private void InitializeFromMember(DbCommandTree tree, EdmMember member, DbExpression instance)
{
//
// Validate the instance
//
if (null == instance)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Property_InstanceRequiredForInstance, "instance");
}
TypeUsage instanceType = TypeUsage.Create(member.DeclaringType);
_instance = new ExpressionLink("Instance", tree, instanceType, instance);
Debug.Assert(!TypeSemantics.IsNullOrNullType(Helper.GetModelTypeUsage(member)), "EdmMember metadata has a TypeUsage of null or NullType");
_property = member;
this.ResultType = Helper.GetModelTypeUsage(member);
}
internal DbPropertyExpression(DbCommandTree cmdTree, EdmProperty propertyInfo, DbExpression instance)
: base(cmdTree, DbExpressionKind.Property)
{
//
// Ensure that the property metadata is non-null and from the same metadata workspace and dataspace as the command tree.
//
cmdTree.TypeHelper.CheckMember(propertyInfo, "propertyInfo");
InitializeFromMember(cmdTree, propertyInfo, instance);
}
internal DbPropertyExpression(DbCommandTree cmdTree, RelationshipEndMember memberInfo, DbExpression instance)
: base(cmdTree, DbExpressionKind.Property)
{
//
// Ensure that the relationship end metadata is non-null and from the same metadata workspace and dataspace as the command tree.
//
cmdTree.TypeHelper.CheckMember(memberInfo, "memberInfo");
InitializeFromMember(cmdTree, memberInfo, instance);
}
internal DbPropertyExpression(DbCommandTree cmdTree, NavigationProperty propertyInfo, DbExpression instance)
: base(cmdTree, DbExpressionKind.Property)
{
//
// Ensure that the navigation property metadata is non-null and from the same metadata workspace and dataspace as the command tree.
//
cmdTree.TypeHelper.CheckMember(propertyInfo, "propertyInfo");
InitializeFromMember(cmdTree, propertyInfo, instance);
}
///
/// Gets the property metadata for the property to retrieve.
///
public EdmMember Property { get { return _property; } }
///
/// Gets or sets an that defines the instance from which the property should be retrieved.
///
/// The expression is null
///
/// The expression is not associated with the DbPropertyExpression's command tree,
/// or its result type is not equal or promotable to the type that defines the property
///
public DbExpression Instance
{
get { return _instance.Expression; }
/*CQT_PUBLIC_API(*/internal/*)*/ set
{
_instance.Expression = value;
}
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents the invocation of a function.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbFunctionExpression : DbExpression
{
private EdmFunction _functionInfo;
private IList _args;
private ExpressionLink _lambdaBody;
internal DbFunctionExpression(DbCommandTree cmdTree, EdmFunction function, DbExpression lambdaBody, IList args)
: base(cmdTree, DbExpressionKind.Function)
{
//
// Ensure that the function metadata is non-null and from the same metadata workspace and dataspace as the command tree.
// Lambda functions are not verified since all of their components (return type, parameter types) have already been
// checked and because they have not been added to a metadata collection because they are not directly associated with
// a particular metadata workspace. Iff a function is a Lambda function will the Lambda body argument be non-null.
//
if (null == lambdaBody)
{
cmdTree.TypeHelper.CheckFunction(function);
}
//
// Non-composable functions or functions including command text are not permitted in expressions -- they can only be
// executed independently
//
if (!function.IsComposableAttribute)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Function_NonComposableInExpression, "function");
}
if (!String.IsNullOrEmpty(function.CommandTextAttribute))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Function_CommandTextInExpression, "function");
}
//
// Functions that return void are not allowed
//
if (null == function.ReturnParameter ||
TypeSemantics.IsNullOrNullType(function.ReturnParameter.TypeUsage))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Function_VoidResultInvalid, "function");
}
//
// Validate the arguments
//
EntityUtil.CheckArgumentNull(args, "args");
_args = new ExpressionList("Arguments", cmdTree, function.Parameters, args);
_functionInfo = function;
//
// Is this a 'Lambda' function invocation?
//
if(lambdaBody != null)
{
_lambdaBody = new ExpressionLink("LambdaBody", cmdTree, lambdaBody);
}
this.ResultType = function.ReturnParameter.TypeUsage;
}
///
/// Gets the metadata for the function to invoke.
///
public EdmFunction Function { get { return _functionInfo; } }
///
/// Gets an list that provides the arguments to the function.
///
public IList Arguments { get { return _args; } }
///
/// Gets a Boolean value indicating whether or not the function to invoke is an inline function definition (Lambda function).
///
/*CQT_PUBLIC_API(*/internal/*)*/ bool IsLambda { get { return _lambdaBody != null; } }
///
/// Gets the DbExpression that provides the Body of the referenced function if that function is a Lambda function
///
/*CQT_PUBLIC_API(*/internal/*)*/ DbExpression LambdaBody
{
get
{
if (_lambdaBody != null)
{
return _lambdaBody.Expression;
}
return null;
}
set
{
if (null == _lambdaBody)
{
throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_Function_BodyOnlyValidForLambda);
}
_lambdaBody.Expression = value;
}
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
#region Lambda function namespace and name
internal static string LambdaFunctionNameSpace { get { return "System.Data.Common.CommandTrees.LambdaFunctions"; } }
internal static string LambdaFunctionName { get { return "Lambda"; } }
#endregion
}
#if METHOD_EXPRESSION
///
/// Represents the invocation of a method.
///
public sealed class MethodExpression : Expression
{
MethodMetadata m_methodInfo;
IList m_args;
ExpressionLink m_inst;
internal MethodExpression(CommandTree cmdTree, MethodMetadata methodInfo, IList 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.
//
cmdTree.TypeHelper.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;
}
///
/// Gets the metadata for the method to invoke.
///
public MethodMetadata Method { get { return m_methodInfo; } }
///
/// Gets the expressions that provide the arguments to the method.
///
public IList Arguments { get { return m_args; } }
///
/// Gets or sets an that defines the instance on which the method should be invoked. Must be null for instance methods.
/// For static properties, Instance will always be null, and attempting to set a new value will result
/// in .
///
/// The expression is null
/// The method is static
///
/// 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
///
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;
}
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of ExpressionVisitor.
/// is null
public override void Accept(ExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed ExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
#endif
///
/// Represents the navigation of a (composition or association) relationship given the 'from' role, the 'to' role and an instance of the from role
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbRelationshipNavigationExpression : DbExpression
{
private RelationshipType _relation;
private RelationshipEndMember _fromRole;
private RelationshipEndMember _toRole;
private ExpressionLink _from;
internal DbRelationshipNavigationExpression(
DbCommandTree cmdTree,
RelationshipEndMember fromEnd,
RelationshipEndMember toEnd,
DbExpression from)
: base(cmdTree, DbExpressionKind.RelationshipNavigation)
{
//
// Validate the relationship ends before use
//
this.CheckEnds(fromEnd, toEnd);
RelationshipType relType = fromEnd.DeclaringType as RelationshipType;
//
// Ensure that the relation type is non-null and from the same metadata workspace as the command tree
//
CommandTreeTypeHelper.CheckType(relType);
//
// Validate that the 'to' relationship end is defined by the same relationship type as the 'from' end
//
if (!relType.Equals(toEnd.DeclaringType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Factory_IncompatibleRelationEnds, "toEnd");
}
//
// Validation was successful so initialize members and verify the source expression against the expected type
//
_relation = relType;
_fromRole = fromEnd;
_toRole = toEnd;
_from = new ExpressionLink("NavigationSource", cmdTree, GetExpectedInstanceType(fromEnd, from), from);
this.ResultType = GetResultType(toEnd);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal DbRelationshipNavigationExpression(
DbCommandTree cmdTree,
RelationshipType type,
string fromEndName,
string toEndName,
DbExpression from)
: base(cmdTree, DbExpressionKind.RelationshipNavigation)
{
//
// Verify that the from and to relation end names are not null
//
EntityUtil.CheckArgumentNull(fromEndName, "fromEndName");
EntityUtil.CheckArgumentNull(toEndName, "toEndName");
//
// Ensure that the relation type is non-null and from the same metadata workspace as the command tree
//
CommandTreeTypeHelper.CheckType(type);
//
// Retrieve the relation end properties with the specified 'from' and 'to' names
//
RelationshipEndMember fromEnd = DbRelationshipNavigationExpression.FindEnd(type.Members, fromEndName, "fromEndName");
RelationshipEndMember toEnd = DbRelationshipNavigationExpression.FindEnd(type.Members, toEndName, "toEndName");
//
// Validate the retrieved relation end properties
//
this.CheckEnds(fromEnd, toEnd);
//
// Validation was successful so initialize members and verify the source expression against the expected type
//
_relation = type;
_fromRole = fromEnd;
_toRole = toEnd;
_from = new ExpressionLink("NavigationSource", cmdTree, GetExpectedInstanceType(fromEnd, from), from);
this.ResultType = GetResultType(toEnd);
}
///
/// Gets the metadata for the relationship over which navigation occurs
///
public RelationshipType Relationship { get { return _relation; } }
///
/// Gets the metadata for the relationship end to navigate from
///
public RelationshipEndMember NavigateFrom { get { return _fromRole; } }
///
/// Gets the metadata for the relationship end to navigate to
///
public RelationshipEndMember NavigateTo { get { return _toRole; } }
///
/// Gets or sets an that specifies the instance of the 'from' relationship end from which navigation should occur.
///
/// The expression is null
///
/// The expression is not associated with the DbRelationshipNavigationExpression's command tree,
/// or its result type is not equal or promotable to the reference type of the NavigateFrom property.
///
///
public DbExpression NavigationSource { get { return _from.Expression; } /*CQT_PUBLIC_API(*/internal/*)*/ set { _from.Expression = value; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// Retrieves a relation end property from a given enumerable collection of members, given the name of the end.
///
/// The enumerable collection of members
/// The name of the end to retrieve
/// The variable name to specify if an exception must be thrown
/// An RelationEndProperty instance that represents the relation end with the specified name
/// If no relation end with the specified name exists
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal static RelationshipEndMember FindEnd(IEnumerable members, string endName, string varName)
{
foreach (EdmMember member in members)
{
RelationshipEndMember end = member as RelationshipEndMember;
if (end != null &&
end.Name.Equals(endName, StringComparison.Ordinal))
{
return end;
}
}
throw EntityUtil.ArgumentOutOfRange(System.Data.Entity.Strings.Cqt_Factory_NoSuchRelationEnd, varName);
}
private static TypeUsage GetExpectedInstanceType(RelationshipEndMember end, DbExpression from)
{
TypeUsage endType = end.TypeUsage;
if (!TypeSemantics.IsReferenceType(endType))
{
//
// The only relation end that is currently allowed to have a non-Reference type is the Child end of
// a composition, in which case the end type must be an entity type.
//
// Debug.Assert(end.Relation.IsComposition && !end.IsParent && (end.Type is EntityType), "Relation end can only have non-Reference type if it is a Composition child end");
endType = TypeHelpers.CreateReferenceTypeUsage(TypeHelpers.GetEdmType(endType));
}
TypeUsage retType = TypeHelpers.GetCommonTypeUsage(endType, from.ResultType);
if (null == retType)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelNav_WrongSourceType(TypeHelpers.GetFullName(endType)), "from");
}
return retType;
}
private static TypeUsage GetResultType(RelationshipEndMember end)
{
TypeUsage retType = end.TypeUsage;
if (!TypeSemantics.IsReferenceType(retType))
{
//
// The only relation end that is currently allowed to have a non-Reference type is the Child end of
// a composition, in which case the end type must be an entity type.
//
//Debug.Assert(end.Relation.IsComposition && !end.IsParent && (end.Type is EntityType), "Relation end can only have non-Reference type if it is a Composition child end");
retType = TypeHelpers.CreateReferenceTypeUsage(TypeHelpers.GetEdmType(retType));
}
//
// If the upper bound is not 1 the result type is a collection of the given type
//
if (RelationshipMultiplicity.Many == end.RelationshipMultiplicity)
{
retType = TypeHelpers.CreateCollectionTypeUsage(retType);
}
return retType;
}
private void CheckEnds(RelationshipEndMember fromEnd, RelationshipEndMember toEnd)
{
//
// Ensure that the 'from' role metadata is non-null and from the same metadata workspace as the command tree
//
this.CommandTree.TypeHelper.CheckMember(fromEnd, "fromEnd");
//
// Ensure that the 'to' role metadata is non-null and from the same metadata workspace as the command tree
//
this.CommandTree.TypeHelper.CheckMember(toEnd, "toEnd");
}
}
///
/// 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 , 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 that
/// constructs an Entity, allowing information about Entities that are related to the newly constructed Entity to be captured.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
internal sealed class DbRelatedEntityRef
{
private readonly RelationshipEndMember _sourceEnd;
private readonly RelationshipEndMember _targetEnd;
private ExpressionLink _targetEntityRef;
//private DbExpression _targetEntityRef;
internal DbRelatedEntityRef(DbCommandTree commandTree, 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
commandTree.TypeHelper.CheckMember(sourceEnd, "sourceEnd");
commandTree.TypeHelper.CheckMember(targetEnd, "targetEnd");
// Validate that the specified target entity ref is:
// 1. Non-null
// 2. Associated with this command tree
_targetEntityRef = new ExpressionLink("TargetEntityReference", commandTree);
_targetEntityRef.InitializeValue(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(targetEnd.TypeUsage).ElementType;
EntityTypeBase targetType = TypeHelpers.GetEdmType(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 remaining state (_targetEntityRef is already initialized)
_targetEnd = targetEnd;
_sourceEnd = sourceEnd;
}
///
/// Retrieves the 'source' end of the relationship navigation satisfied by this related entity Ref
///
internal RelationshipEndMember SourceEnd { get { return _sourceEnd; } }
///
/// Retrieves the 'target' end of the relationship navigation satisfied by this related entity Ref
///
internal RelationshipEndMember TargetEnd { get { return _targetEnd; } }
///
/// Retrieves the entity Ref that is the result of navigating from the source to the target end of this related entity Ref
///
internal DbExpression TargetEntityReference { get { return _targetEntityRef.Expression; } set { _targetEntityRef.Expression = value; } }
}
///
/// Represents the construction of a new instance of a given type, including set and record types.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbNewInstanceExpression : DbExpression
{
private IList _elements;
private System.Collections.ObjectModel.ReadOnlyCollection _relatedEntityRefs;
internal DbNewInstanceExpression(DbCommandTree cmdTree, TypeUsage type, IList args)
: base(cmdTree, DbExpressionKind.NewInstance)
{
//
// Ensure that the type is non-null, valid and not NullType
//
cmdTree.TypeHelper.CheckType(type);
//
// Type-specific validation
//
CollectionType collectionType = null;
if( TypeHelpers.TryGetEdmType(type, out collectionType) &&
collectionType != null)
{
TypeUsage elementType = collectionType.TypeUsage;
//
// Is this an empty collection constructor?
//
if (null == args || 0 == args.Count)
{
_elements = new ExpressionList("Arguments", cmdTree, 0);
}
else
{
_elements = new ExpressionList("Arguments", cmdTree, elementType, args);
}
}
else
{
EntityUtil.CheckArgumentNull(args, "args");
_elements = CreateStructuralArgumentList(cmdTree, type, type.EdmType as StructuralType, args);
}
this.ResultType = type;
}
internal DbNewInstanceExpression(DbCommandTree cmdTree, EntityType entityType, IList attributeValues, IList relationships)
: base(cmdTree, DbExpressionKind.NewInstance)
{
EntityUtil.CheckArgumentNull(entityType, "entityType");
EntityUtil.CheckArgumentNull(attributeValues, "attributeValues");
EntityUtil.CheckArgumentNull(relationships, "relationships");
TypeUsage resultType = CommandTreeTypeHelper.CreateResultType(entityType);
cmdTree.TypeHelper.CheckType(resultType, "entityType");
_elements = CreateStructuralArgumentList(cmdTree, resultType, entityType, attributeValues);
if (relationships.Count > 0)
{
List relatedRefs = new List(relationships.Count);
for (int idx = 0; idx < relationships.Count; idx++)
{
DbRelatedEntityRef relatedRef = relationships[idx];
EntityUtil.CheckArgumentNull(relatedRef, CommandTreeUtils.FormatIndex("relationships", idx));
// The target entity ref must be associated with the same command tree as this new instance expression
if (!object.ReferenceEquals(relatedRef.TargetEntityReference.CommandTree, cmdTree))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_IncompatibleRelatedEntity_TargetEntityNotValid, CommandTreeUtils.FormatIndex("relationships", idx));
}
// The source end type must be the same type or a supertype of the Entity instance type
EntityTypeBase expectedSourceType = TypeHelpers.GetEdmType(relatedRef.SourceEnd.TypeUsage).ElementType;
if (!entityType.EdmEquals(expectedSourceType) &&
!entityType.IsSubtypeOf(expectedSourceType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_IncompatibleRelatedEntity_SourceTypeNotValid, CommandTreeUtils.FormatIndex("relationships", idx));
}
relatedRefs.Add(relatedRef);
}
_relatedEntityRefs = relatedRefs.AsReadOnly();
}
this.ResultType = resultType;
}
///
/// Gets an list that provides the property/column values or set elements for the new instance.
///
public IList Arguments { get { return _elements; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
internal bool HasRelatedEntityReferences { get { return (_relatedEntityRefs != null); } }
///
/// Gets the related entity references (if any) for an entity constructor.
/// May be null if no related entities were specified - use the property to determine this.
///
internal System.Collections.ObjectModel.ReadOnlyCollection RelatedEntityReferences { get { return _relatedEntityRefs; } }
private static IList CreateStructuralArgumentList(DbCommandTree cmdTree, TypeUsage type, StructuralType structType, IList args)
{
if (null == structType)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_StructuralTypeRequired, "type");
}
if (structType.Members.Count < 1)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_CannotInstantiateMemberlessType(TypeHelpers.GetFullName(type)), "type");
}
if (structType.Abstract)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_CannotInstantiateAbstractType(TypeHelpers.GetFullName(type)), "type");
}
return new ExpressionList("Arguments",
cmdTree,
TypeHelpers.GetAllStructuralMembers(structType),
args);
}
}
///
/// Represents a (strongly typed) reference to a specific instance within a given entity set.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbRefExpression : DbUnaryExpression
{
EntitySet _entitySet;
internal DbRefExpression(DbCommandTree cmdTree, EntitySet entitySet, DbExpression refKeys, EntityType entityType)
: base(cmdTree, DbExpressionKind.Ref)
{
EntityUtil.CheckArgumentNull(entitySet, "entitySet");
EntityUtil.CheckArgumentNull(refKeys, "refKeys");
CommandTreeTypeHelper.CheckType(entityType);
cmdTree.TypeHelper.CheckEntitySet(entitySet);
//
// Verify that the specified return type of the Ref operation is actually in
// the same hierarchy as the Entity type of the specified Entity set.
//
if (!TypeSemantics.IsValidPolymorphicCast(entitySet.ElementType, entityType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Ref_PolymorphicArgRequired);
}
//
// The Argument DbExpression must construct a set of values of the same types as the Key members of the Entity
// The names of the columns in the record type constructed by the Argument are not important, only that the
// number of columns is the same as the number of Key members and that for each Key member the corresponding
// column (based on order) is of a promotable type.
// To enforce this the ArgumentLink ExpressionLink's ExpectedType is initialized to a record type based on the
// names and types of the Key members. Since the promotability check used in ExpressionLink will ignore the names
// of the ExpectedType's columns, ExpressionLink will therefore enforce the required level of type correctness
// on the argument expression both here when it's value is first set (by calling ArgumentLink.InitializeValue)
// and subsequently when the value of the Argument property is set to a new value.
//
// Set the expected type to be the record type created based on the Key members
//
TypeUsage keyType = CommandTreeTypeHelper.CreateResultType(TypeHelpers.CreateKeyRowType(entitySet.ElementType, cmdTree.MetadataWorkspace));
this.ArgumentLink.SetExpectedType(keyType);
//
// Attempt to initialize the Argument to the specified DbExpression.
// If the type is not promotable to the record type set above (i.e. does
// not have the same number of columns, with the type of each corresponding
// column promotable to the column type of the record's column, names ignored)
// then the ExpressionLink will throw at this point.
//
this.ArgumentLink.InitializeValue(refKeys);
cmdTree.TrackContainer(entitySet.EntityContainer);
// Initialize the entitySet and result type properties.
// The result type of the expression is Ref.
_entitySet = entitySet;
this.ResultType = CommandTreeTypeHelper.CreateReferenceResultType(entityType);
}
///
/// Gets the metadata for the entity set that contains the instance.
///
public EntitySet EntitySet { get { return _entitySet; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents the retrieval of a given entity using the specified Ref.
///
[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(DbCommandTree cmdTree, DbExpression refExpr)
: base(cmdTree, DbExpressionKind.Deref, refExpr)
{
//
// Ensure that the operand is actually of a reference type.
//
EntityType entityType;
if(!TypeHelpers.TryGetRefEntityType(this.Argument.ResultType, out entityType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_DeRef_RefRequired, "Argument");
}
//
// Result Type is the element type of the reference type
//
this.ResultType = CommandTreeTypeHelper.CreateResultType(entityType);
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents a 'scan' of all elements of a given entity set.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbScanExpression : DbExpression
{
private EntitySetBase _targetSet;
internal DbScanExpression(DbCommandTree cmdTree, EntitySetBase entitySet)
: base(cmdTree, DbExpressionKind.Scan)
{
cmdTree.TypeHelper.CheckEntitySet(entitySet);
cmdTree.TrackContainer(entitySet.EntityContainer);
_targetSet = entitySet;
this.ResultType = CommandTreeTypeHelper.CreateCollectionResultType(entitySet.ElementType);
}
///
/// Gets the metadata for the referenced entity or relationship set.
///
public EntitySetBase Target { get { return _targetSet; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees.Internal;
namespace System.Data.Common.CommandTrees
{
///
/// Represents a constant value.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbConstantExpression : DbExpression
{
private object _value;
internal DbConstantExpression(DbCommandTree commandTree, object value)
: base(commandTree, DbExpressionKind.Constant)
{
if (null == value)
{
throw EntityUtil.ArgumentNull("value");
}
//
// Check that typeof(value) is actually a valid constant (i.e. primitive) type
//
PrimitiveTypeKind primitiveTypeKind;
if (!CommandTreeUtils.TryGetPrimtiveTypeKind(value.GetType(), out primitiveTypeKind))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Constant_InvalidType, "value");
}
TypeUsage typeMeta = TypeHelpers.GetLiteralTypeUsage(primitiveTypeKind);
//
// Set the value
//
_value = value;
this.ResultType = typeMeta;
}
internal DbConstantExpression(DbCommandTree commandTree, object value, TypeUsage constantType)
: base(commandTree, DbExpressionKind.Constant)
{
//
// Basic validation of constant value and constant type (non-null, read-only, etc)
//
EntityUtil.CheckArgumentNull(value, "value");
commandTree.TypeHelper.CheckType(constantType, "constantType");
//
// Verify that constantType is a primitive type and that value is an instance of that primitive type
// Note that the value is not validated against applicable facets (such as MaxLength for a string value),
// this is left to the server.
//
PrimitiveType primitiveType;
if (!TypeHelpers.TryGetEdmType(constantType, out primitiveType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Constant_InvalidConstantType(constantType.ToString()), "constantType");
}
PrimitiveTypeKind valueKind;
if (!CommandTreeUtils.TryGetPrimtiveTypeKind(value.GetType(), out valueKind) ||
primitiveType.PrimitiveTypeKind != valueKind)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Constant_InvalidValueForType(constantType.ToString()), "value");
}
//
// Set the value
//
_value = value;
this.ResultType = constantType;
}
///
/// Gets the constant value.
///
public object Value { get { return _value; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents null.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbNullExpression : DbExpression
{
internal DbNullExpression(DbCommandTree commandTree, TypeUsage type)
: base(commandTree, DbExpressionKind.Null)
{
commandTree.TypeHelper.CheckType(type);
this.ResultType = type;
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents a reference to a variable that is currently in scope.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbVariableReferenceExpression : DbExpression
{
private string _name;
internal DbVariableReferenceExpression(DbCommandTree cmdTree, TypeUsage type, string name)
: base(cmdTree, DbExpressionKind.VariableReference)
{
if (string.IsNullOrEmpty(name))
{
throw EntityUtil.ArgumentNull("name");
}
//
// Verify the type of the reference. NullType is not allowed in Var or Parameter references.
//
cmdTree.TypeHelper.CheckType(type);
_name = name;
this.ResultType = type;
}
///
/// Gets the name of the referenced variable.
///
public string VariableName { get { return _name; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents a reference to a parameter declared on the command tree that contains this expression.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbParameterReferenceExpression : DbExpression
{
private string _name;
internal DbParameterReferenceExpression(DbCommandTree cmdTree, TypeUsage type, string name)
: base(cmdTree, DbExpressionKind.ParameterReference)
{
EntityUtil.CheckArgumentNull(name, "name");
// DbCommandTree.CreateParameterRefExpression should check that a parameter with the given name exists,
// and DbCommandTree.AddParameter should have already verified that the name is valid, so this need only
// be asserted here.
Debug.Assert(DbCommandTree.IsValidParameterName(name), string.Format(CultureInfo.InvariantCulture, "Invalid parameter name passed to DbParameterReferenceExpression constructor: '{0}'", name));
//
// Verify the type of the reference. NullType is not allowed in Var or Parameter references.
//
cmdTree.TypeHelper.CheckType(type);
_name = name;
this.ResultType = type;
}
///
/// Gets the name of the referenced parameter.
///
public string ParameterName { get { return _name; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents the retrieval of a static or instance property.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbPropertyExpression : DbExpression
{
private EdmMember _property;
private ExpressionLink _instance;
private void InitializeFromMember(DbCommandTree tree, EdmMember member, DbExpression instance)
{
//
// Validate the instance
//
if (null == instance)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Property_InstanceRequiredForInstance, "instance");
}
TypeUsage instanceType = TypeUsage.Create(member.DeclaringType);
_instance = new ExpressionLink("Instance", tree, instanceType, instance);
Debug.Assert(!TypeSemantics.IsNullOrNullType(Helper.GetModelTypeUsage(member)), "EdmMember metadata has a TypeUsage of null or NullType");
_property = member;
this.ResultType = Helper.GetModelTypeUsage(member);
}
internal DbPropertyExpression(DbCommandTree cmdTree, EdmProperty propertyInfo, DbExpression instance)
: base(cmdTree, DbExpressionKind.Property)
{
//
// Ensure that the property metadata is non-null and from the same metadata workspace and dataspace as the command tree.
//
cmdTree.TypeHelper.CheckMember(propertyInfo, "propertyInfo");
InitializeFromMember(cmdTree, propertyInfo, instance);
}
internal DbPropertyExpression(DbCommandTree cmdTree, RelationshipEndMember memberInfo, DbExpression instance)
: base(cmdTree, DbExpressionKind.Property)
{
//
// Ensure that the relationship end metadata is non-null and from the same metadata workspace and dataspace as the command tree.
//
cmdTree.TypeHelper.CheckMember(memberInfo, "memberInfo");
InitializeFromMember(cmdTree, memberInfo, instance);
}
internal DbPropertyExpression(DbCommandTree cmdTree, NavigationProperty propertyInfo, DbExpression instance)
: base(cmdTree, DbExpressionKind.Property)
{
//
// Ensure that the navigation property metadata is non-null and from the same metadata workspace and dataspace as the command tree.
//
cmdTree.TypeHelper.CheckMember(propertyInfo, "propertyInfo");
InitializeFromMember(cmdTree, propertyInfo, instance);
}
///
/// Gets the property metadata for the property to retrieve.
///
public EdmMember Property { get { return _property; } }
///
/// Gets or sets an that defines the instance from which the property should be retrieved.
///
/// The expression is null
///
/// The expression is not associated with the DbPropertyExpression's command tree,
/// or its result type is not equal or promotable to the type that defines the property
///
public DbExpression Instance
{
get { return _instance.Expression; }
/*CQT_PUBLIC_API(*/internal/*)*/ set
{
_instance.Expression = value;
}
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents the invocation of a function.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbFunctionExpression : DbExpression
{
private EdmFunction _functionInfo;
private IList _args;
private ExpressionLink _lambdaBody;
internal DbFunctionExpression(DbCommandTree cmdTree, EdmFunction function, DbExpression lambdaBody, IList args)
: base(cmdTree, DbExpressionKind.Function)
{
//
// Ensure that the function metadata is non-null and from the same metadata workspace and dataspace as the command tree.
// Lambda functions are not verified since all of their components (return type, parameter types) have already been
// checked and because they have not been added to a metadata collection because they are not directly associated with
// a particular metadata workspace. Iff a function is a Lambda function will the Lambda body argument be non-null.
//
if (null == lambdaBody)
{
cmdTree.TypeHelper.CheckFunction(function);
}
//
// Non-composable functions or functions including command text are not permitted in expressions -- they can only be
// executed independently
//
if (!function.IsComposableAttribute)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Function_NonComposableInExpression, "function");
}
if (!String.IsNullOrEmpty(function.CommandTextAttribute))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Function_CommandTextInExpression, "function");
}
//
// Functions that return void are not allowed
//
if (null == function.ReturnParameter ||
TypeSemantics.IsNullOrNullType(function.ReturnParameter.TypeUsage))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Function_VoidResultInvalid, "function");
}
//
// Validate the arguments
//
EntityUtil.CheckArgumentNull(args, "args");
_args = new ExpressionList("Arguments", cmdTree, function.Parameters, args);
_functionInfo = function;
//
// Is this a 'Lambda' function invocation?
//
if(lambdaBody != null)
{
_lambdaBody = new ExpressionLink("LambdaBody", cmdTree, lambdaBody);
}
this.ResultType = function.ReturnParameter.TypeUsage;
}
///
/// Gets the metadata for the function to invoke.
///
public EdmFunction Function { get { return _functionInfo; } }
///
/// Gets an list that provides the arguments to the function.
///
public IList Arguments { get { return _args; } }
///
/// Gets a Boolean value indicating whether or not the function to invoke is an inline function definition (Lambda function).
///
/*CQT_PUBLIC_API(*/internal/*)*/ bool IsLambda { get { return _lambdaBody != null; } }
///
/// Gets the DbExpression that provides the Body of the referenced function if that function is a Lambda function
///
/*CQT_PUBLIC_API(*/internal/*)*/ DbExpression LambdaBody
{
get
{
if (_lambdaBody != null)
{
return _lambdaBody.Expression;
}
return null;
}
set
{
if (null == _lambdaBody)
{
throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_Function_BodyOnlyValidForLambda);
}
_lambdaBody.Expression = value;
}
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
#region Lambda function namespace and name
internal static string LambdaFunctionNameSpace { get { return "System.Data.Common.CommandTrees.LambdaFunctions"; } }
internal static string LambdaFunctionName { get { return "Lambda"; } }
#endregion
}
#if METHOD_EXPRESSION
///
/// Represents the invocation of a method.
///
public sealed class MethodExpression : Expression
{
MethodMetadata m_methodInfo;
IList m_args;
ExpressionLink m_inst;
internal MethodExpression(CommandTree cmdTree, MethodMetadata methodInfo, IList 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.
//
cmdTree.TypeHelper.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;
}
///
/// Gets the metadata for the method to invoke.
///
public MethodMetadata Method { get { return m_methodInfo; } }
///
/// Gets the expressions that provide the arguments to the method.
///
public IList Arguments { get { return m_args; } }
///
/// Gets or sets an that defines the instance on which the method should be invoked. Must be null for instance methods.
/// For static properties, Instance will always be null, and attempting to set a new value will result
/// in .
///
/// The expression is null
/// The method is static
///
/// 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
///
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;
}
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of ExpressionVisitor.
/// is null
public override void Accept(ExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed ExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
#endif
///
/// Represents the navigation of a (composition or association) relationship given the 'from' role, the 'to' role and an instance of the from role
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbRelationshipNavigationExpression : DbExpression
{
private RelationshipType _relation;
private RelationshipEndMember _fromRole;
private RelationshipEndMember _toRole;
private ExpressionLink _from;
internal DbRelationshipNavigationExpression(
DbCommandTree cmdTree,
RelationshipEndMember fromEnd,
RelationshipEndMember toEnd,
DbExpression from)
: base(cmdTree, DbExpressionKind.RelationshipNavigation)
{
//
// Validate the relationship ends before use
//
this.CheckEnds(fromEnd, toEnd);
RelationshipType relType = fromEnd.DeclaringType as RelationshipType;
//
// Ensure that the relation type is non-null and from the same metadata workspace as the command tree
//
CommandTreeTypeHelper.CheckType(relType);
//
// Validate that the 'to' relationship end is defined by the same relationship type as the 'from' end
//
if (!relType.Equals(toEnd.DeclaringType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Factory_IncompatibleRelationEnds, "toEnd");
}
//
// Validation was successful so initialize members and verify the source expression against the expected type
//
_relation = relType;
_fromRole = fromEnd;
_toRole = toEnd;
_from = new ExpressionLink("NavigationSource", cmdTree, GetExpectedInstanceType(fromEnd, from), from);
this.ResultType = GetResultType(toEnd);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal DbRelationshipNavigationExpression(
DbCommandTree cmdTree,
RelationshipType type,
string fromEndName,
string toEndName,
DbExpression from)
: base(cmdTree, DbExpressionKind.RelationshipNavigation)
{
//
// Verify that the from and to relation end names are not null
//
EntityUtil.CheckArgumentNull(fromEndName, "fromEndName");
EntityUtil.CheckArgumentNull(toEndName, "toEndName");
//
// Ensure that the relation type is non-null and from the same metadata workspace as the command tree
//
CommandTreeTypeHelper.CheckType(type);
//
// Retrieve the relation end properties with the specified 'from' and 'to' names
//
RelationshipEndMember fromEnd = DbRelationshipNavigationExpression.FindEnd(type.Members, fromEndName, "fromEndName");
RelationshipEndMember toEnd = DbRelationshipNavigationExpression.FindEnd(type.Members, toEndName, "toEndName");
//
// Validate the retrieved relation end properties
//
this.CheckEnds(fromEnd, toEnd);
//
// Validation was successful so initialize members and verify the source expression against the expected type
//
_relation = type;
_fromRole = fromEnd;
_toRole = toEnd;
_from = new ExpressionLink("NavigationSource", cmdTree, GetExpectedInstanceType(fromEnd, from), from);
this.ResultType = GetResultType(toEnd);
}
///
/// Gets the metadata for the relationship over which navigation occurs
///
public RelationshipType Relationship { get { return _relation; } }
///
/// Gets the metadata for the relationship end to navigate from
///
public RelationshipEndMember NavigateFrom { get { return _fromRole; } }
///
/// Gets the metadata for the relationship end to navigate to
///
public RelationshipEndMember NavigateTo { get { return _toRole; } }
///
/// Gets or sets an that specifies the instance of the 'from' relationship end from which navigation should occur.
///
/// The expression is null
///
/// The expression is not associated with the DbRelationshipNavigationExpression's command tree,
/// or its result type is not equal or promotable to the reference type of the NavigateFrom property.
///
///
public DbExpression NavigationSource { get { return _from.Expression; } /*CQT_PUBLIC_API(*/internal/*)*/ set { _from.Expression = value; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// Retrieves a relation end property from a given enumerable collection of members, given the name of the end.
///
/// The enumerable collection of members
/// The name of the end to retrieve
/// The variable name to specify if an exception must be thrown
/// An RelationEndProperty instance that represents the relation end with the specified name
/// If no relation end with the specified name exists
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal static RelationshipEndMember FindEnd(IEnumerable members, string endName, string varName)
{
foreach (EdmMember member in members)
{
RelationshipEndMember end = member as RelationshipEndMember;
if (end != null &&
end.Name.Equals(endName, StringComparison.Ordinal))
{
return end;
}
}
throw EntityUtil.ArgumentOutOfRange(System.Data.Entity.Strings.Cqt_Factory_NoSuchRelationEnd, varName);
}
private static TypeUsage GetExpectedInstanceType(RelationshipEndMember end, DbExpression from)
{
TypeUsage endType = end.TypeUsage;
if (!TypeSemantics.IsReferenceType(endType))
{
//
// The only relation end that is currently allowed to have a non-Reference type is the Child end of
// a composition, in which case the end type must be an entity type.
//
// Debug.Assert(end.Relation.IsComposition && !end.IsParent && (end.Type is EntityType), "Relation end can only have non-Reference type if it is a Composition child end");
endType = TypeHelpers.CreateReferenceTypeUsage(TypeHelpers.GetEdmType(endType));
}
TypeUsage retType = TypeHelpers.GetCommonTypeUsage(endType, from.ResultType);
if (null == retType)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_RelNav_WrongSourceType(TypeHelpers.GetFullName(endType)), "from");
}
return retType;
}
private static TypeUsage GetResultType(RelationshipEndMember end)
{
TypeUsage retType = end.TypeUsage;
if (!TypeSemantics.IsReferenceType(retType))
{
//
// The only relation end that is currently allowed to have a non-Reference type is the Child end of
// a composition, in which case the end type must be an entity type.
//
//Debug.Assert(end.Relation.IsComposition && !end.IsParent && (end.Type is EntityType), "Relation end can only have non-Reference type if it is a Composition child end");
retType = TypeHelpers.CreateReferenceTypeUsage(TypeHelpers.GetEdmType(retType));
}
//
// If the upper bound is not 1 the result type is a collection of the given type
//
if (RelationshipMultiplicity.Many == end.RelationshipMultiplicity)
{
retType = TypeHelpers.CreateCollectionTypeUsage(retType);
}
return retType;
}
private void CheckEnds(RelationshipEndMember fromEnd, RelationshipEndMember toEnd)
{
//
// Ensure that the 'from' role metadata is non-null and from the same metadata workspace as the command tree
//
this.CommandTree.TypeHelper.CheckMember(fromEnd, "fromEnd");
//
// Ensure that the 'to' role metadata is non-null and from the same metadata workspace as the command tree
//
this.CommandTree.TypeHelper.CheckMember(toEnd, "toEnd");
}
}
///
/// 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 , 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 that
/// constructs an Entity, allowing information about Entities that are related to the newly constructed Entity to be captured.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
internal sealed class DbRelatedEntityRef
{
private readonly RelationshipEndMember _sourceEnd;
private readonly RelationshipEndMember _targetEnd;
private ExpressionLink _targetEntityRef;
//private DbExpression _targetEntityRef;
internal DbRelatedEntityRef(DbCommandTree commandTree, 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
commandTree.TypeHelper.CheckMember(sourceEnd, "sourceEnd");
commandTree.TypeHelper.CheckMember(targetEnd, "targetEnd");
// Validate that the specified target entity ref is:
// 1. Non-null
// 2. Associated with this command tree
_targetEntityRef = new ExpressionLink("TargetEntityReference", commandTree);
_targetEntityRef.InitializeValue(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(targetEnd.TypeUsage).ElementType;
EntityTypeBase targetType = TypeHelpers.GetEdmType(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 remaining state (_targetEntityRef is already initialized)
_targetEnd = targetEnd;
_sourceEnd = sourceEnd;
}
///
/// Retrieves the 'source' end of the relationship navigation satisfied by this related entity Ref
///
internal RelationshipEndMember SourceEnd { get { return _sourceEnd; } }
///
/// Retrieves the 'target' end of the relationship navigation satisfied by this related entity Ref
///
internal RelationshipEndMember TargetEnd { get { return _targetEnd; } }
///
/// Retrieves the entity Ref that is the result of navigating from the source to the target end of this related entity Ref
///
internal DbExpression TargetEntityReference { get { return _targetEntityRef.Expression; } set { _targetEntityRef.Expression = value; } }
}
///
/// Represents the construction of a new instance of a given type, including set and record types.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbNewInstanceExpression : DbExpression
{
private IList _elements;
private System.Collections.ObjectModel.ReadOnlyCollection _relatedEntityRefs;
internal DbNewInstanceExpression(DbCommandTree cmdTree, TypeUsage type, IList args)
: base(cmdTree, DbExpressionKind.NewInstance)
{
//
// Ensure that the type is non-null, valid and not NullType
//
cmdTree.TypeHelper.CheckType(type);
//
// Type-specific validation
//
CollectionType collectionType = null;
if( TypeHelpers.TryGetEdmType(type, out collectionType) &&
collectionType != null)
{
TypeUsage elementType = collectionType.TypeUsage;
//
// Is this an empty collection constructor?
//
if (null == args || 0 == args.Count)
{
_elements = new ExpressionList("Arguments", cmdTree, 0);
}
else
{
_elements = new ExpressionList("Arguments", cmdTree, elementType, args);
}
}
else
{
EntityUtil.CheckArgumentNull(args, "args");
_elements = CreateStructuralArgumentList(cmdTree, type, type.EdmType as StructuralType, args);
}
this.ResultType = type;
}
internal DbNewInstanceExpression(DbCommandTree cmdTree, EntityType entityType, IList attributeValues, IList relationships)
: base(cmdTree, DbExpressionKind.NewInstance)
{
EntityUtil.CheckArgumentNull(entityType, "entityType");
EntityUtil.CheckArgumentNull(attributeValues, "attributeValues");
EntityUtil.CheckArgumentNull(relationships, "relationships");
TypeUsage resultType = CommandTreeTypeHelper.CreateResultType(entityType);
cmdTree.TypeHelper.CheckType(resultType, "entityType");
_elements = CreateStructuralArgumentList(cmdTree, resultType, entityType, attributeValues);
if (relationships.Count > 0)
{
List relatedRefs = new List(relationships.Count);
for (int idx = 0; idx < relationships.Count; idx++)
{
DbRelatedEntityRef relatedRef = relationships[idx];
EntityUtil.CheckArgumentNull(relatedRef, CommandTreeUtils.FormatIndex("relationships", idx));
// The target entity ref must be associated with the same command tree as this new instance expression
if (!object.ReferenceEquals(relatedRef.TargetEntityReference.CommandTree, cmdTree))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_IncompatibleRelatedEntity_TargetEntityNotValid, CommandTreeUtils.FormatIndex("relationships", idx));
}
// The source end type must be the same type or a supertype of the Entity instance type
EntityTypeBase expectedSourceType = TypeHelpers.GetEdmType(relatedRef.SourceEnd.TypeUsage).ElementType;
if (!entityType.EdmEquals(expectedSourceType) &&
!entityType.IsSubtypeOf(expectedSourceType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_IncompatibleRelatedEntity_SourceTypeNotValid, CommandTreeUtils.FormatIndex("relationships", idx));
}
relatedRefs.Add(relatedRef);
}
_relatedEntityRefs = relatedRefs.AsReadOnly();
}
this.ResultType = resultType;
}
///
/// Gets an list that provides the property/column values or set elements for the new instance.
///
public IList Arguments { get { return _elements; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
internal bool HasRelatedEntityReferences { get { return (_relatedEntityRefs != null); } }
///
/// Gets the related entity references (if any) for an entity constructor.
/// May be null if no related entities were specified - use the property to determine this.
///
internal System.Collections.ObjectModel.ReadOnlyCollection RelatedEntityReferences { get { return _relatedEntityRefs; } }
private static IList CreateStructuralArgumentList(DbCommandTree cmdTree, TypeUsage type, StructuralType structType, IList args)
{
if (null == structType)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_StructuralTypeRequired, "type");
}
if (structType.Members.Count < 1)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_CannotInstantiateMemberlessType(TypeHelpers.GetFullName(type)), "type");
}
if (structType.Abstract)
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_NewInstance_CannotInstantiateAbstractType(TypeHelpers.GetFullName(type)), "type");
}
return new ExpressionList("Arguments",
cmdTree,
TypeHelpers.GetAllStructuralMembers(structType),
args);
}
}
///
/// Represents a (strongly typed) reference to a specific instance within a given entity set.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbRefExpression : DbUnaryExpression
{
EntitySet _entitySet;
internal DbRefExpression(DbCommandTree cmdTree, EntitySet entitySet, DbExpression refKeys, EntityType entityType)
: base(cmdTree, DbExpressionKind.Ref)
{
EntityUtil.CheckArgumentNull(entitySet, "entitySet");
EntityUtil.CheckArgumentNull(refKeys, "refKeys");
CommandTreeTypeHelper.CheckType(entityType);
cmdTree.TypeHelper.CheckEntitySet(entitySet);
//
// Verify that the specified return type of the Ref operation is actually in
// the same hierarchy as the Entity type of the specified Entity set.
//
if (!TypeSemantics.IsValidPolymorphicCast(entitySet.ElementType, entityType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Ref_PolymorphicArgRequired);
}
//
// The Argument DbExpression must construct a set of values of the same types as the Key members of the Entity
// The names of the columns in the record type constructed by the Argument are not important, only that the
// number of columns is the same as the number of Key members and that for each Key member the corresponding
// column (based on order) is of a promotable type.
// To enforce this the ArgumentLink ExpressionLink's ExpectedType is initialized to a record type based on the
// names and types of the Key members. Since the promotability check used in ExpressionLink will ignore the names
// of the ExpectedType's columns, ExpressionLink will therefore enforce the required level of type correctness
// on the argument expression both here when it's value is first set (by calling ArgumentLink.InitializeValue)
// and subsequently when the value of the Argument property is set to a new value.
//
// Set the expected type to be the record type created based on the Key members
//
TypeUsage keyType = CommandTreeTypeHelper.CreateResultType(TypeHelpers.CreateKeyRowType(entitySet.ElementType, cmdTree.MetadataWorkspace));
this.ArgumentLink.SetExpectedType(keyType);
//
// Attempt to initialize the Argument to the specified DbExpression.
// If the type is not promotable to the record type set above (i.e. does
// not have the same number of columns, with the type of each corresponding
// column promotable to the column type of the record's column, names ignored)
// then the ExpressionLink will throw at this point.
//
this.ArgumentLink.InitializeValue(refKeys);
cmdTree.TrackContainer(entitySet.EntityContainer);
// Initialize the entitySet and result type properties.
// The result type of the expression is Ref.
_entitySet = entitySet;
this.ResultType = CommandTreeTypeHelper.CreateReferenceResultType(entityType);
}
///
/// Gets the metadata for the entity set that contains the instance.
///
public EntitySet EntitySet { get { return _entitySet; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents the retrieval of a given entity using the specified Ref.
///
[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(DbCommandTree cmdTree, DbExpression refExpr)
: base(cmdTree, DbExpressionKind.Deref, refExpr)
{
//
// Ensure that the operand is actually of a reference type.
//
EntityType entityType;
if(!TypeHelpers.TryGetRefEntityType(this.Argument.ResultType, out entityType))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_DeRef_RefRequired, "Argument");
}
//
// Result Type is the element type of the reference type
//
this.ResultType = CommandTreeTypeHelper.CreateResultType(entityType);
}
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
///
/// Represents a 'scan' of all elements of a given entity set.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db")]
public sealed class DbScanExpression : DbExpression
{
private EntitySetBase _targetSet;
internal DbScanExpression(DbCommandTree cmdTree, EntitySetBase entitySet)
: base(cmdTree, DbExpressionKind.Scan)
{
cmdTree.TypeHelper.CheckEntitySet(entitySet);
cmdTree.TrackContainer(entitySet.EntityContainer);
_targetSet = entitySet;
this.ResultType = CommandTreeTypeHelper.CreateCollectionResultType(entitySet.ElementType);
}
///
/// Gets the metadata for the referenced entity or relationship set.
///
public EntitySetBase Target { get { return _targetSet; } }
///
/// The visitor pattern method for expression visitors that do not produce a result value.
///
/// An instance of DbExpressionVisitor.
/// is null
public override void Accept(DbExpressionVisitor visitor) { if (visitor != null) { visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
///
/// The visitor pattern method for expression visitors that produce a result value of a specific type.
///
/// An instance of a typed DbExpressionVisitor that produces a result value of type TResultType.
/// The type of the result produced by
/// is null
/// An instance of .
public override TResultType Accept(DbExpressionVisitor visitor) { if (visitor != null) { return visitor.Visit(this); } else { throw EntityUtil.ArgumentNull("visitor"); } }
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XamlTemplateSerializer.cs
- LinqDataSourceContextData.cs
- Triangle.cs
- BehaviorEditorPart.cs
- HostSecurityManager.cs
- DataSourceHelper.cs
- Interop.cs
- WindowsAuthenticationEventArgs.cs
- MenuTracker.cs
- UserPreferenceChangedEventArgs.cs
- DataTableReader.cs
- DesignerSerializationOptionsAttribute.cs
- ModelVisual3D.cs
- OdbcEnvironmentHandle.cs
- EventLogger.cs
- DynamicPropertyHolder.cs
- FillErrorEventArgs.cs
- ClientRuntimeConfig.cs
- AutoResetEvent.cs
- CachedBitmap.cs
- TransformerConfigurationWizardBase.cs
- ReliableMessagingHelpers.cs
- LinqDataSourceView.cs
- VideoDrawing.cs
- StreamGeometry.cs
- ChunkedMemoryStream.cs
- DiscriminatorMap.cs
- EditBehavior.cs
- ExpressionLink.cs
- QilReference.cs
- ControlCachePolicy.cs
- ToolStripSeparatorRenderEventArgs.cs
- EmptyEnumerator.cs
- CodeDefaultValueExpression.cs
- WinHttpWebProxyFinder.cs
- TraceSection.cs
- GridViewColumnCollection.cs
- AssociationTypeEmitter.cs
- TraceEventCache.cs
- AttachedPropertyMethodSelector.cs
- dtdvalidator.cs
- PasswordRecoveryAutoFormat.cs
- OperatorExpressions.cs
- RoleService.cs
- SelectionPattern.cs
- ObjectView.cs
- ParameterExpression.cs
- ConnectionPoint.cs
- ContractBase.cs
- ContextStack.cs
- selecteditemcollection.cs
- NativeMethods.cs
- webproxy.cs
- PhysicalFontFamily.cs
- CompilerResults.cs
- Vector3DCollection.cs
- ConvertBinder.cs
- PermissionToken.cs
- loginstatus.cs
- RenderCapability.cs
- _ChunkParse.cs
- XsltLibrary.cs
- OrthographicCamera.cs
- CodeGenerator.cs
- BinaryNode.cs
- EntityContainerAssociationSet.cs
- GuidTagList.cs
- DesignerToolboxInfo.cs
- UserControlDesigner.cs
- KeyValueConfigurationElement.cs
- IRCollection.cs
- DispatcherOperation.cs
- BooleanToVisibilityConverter.cs
- CommandPlan.cs
- BookmarkEventArgs.cs
- SymLanguageType.cs
- KnownTypesHelper.cs
- AutoResetEvent.cs
- DiagnosticsConfigurationHandler.cs
- TraceEventCache.cs
- XmlUnspecifiedAttribute.cs
- TagPrefixAttribute.cs
- ExtensibleClassFactory.cs
- XamlInt32CollectionSerializer.cs
- cryptoapiTransform.cs
- SerializationInfo.cs
- ConfigurationSettings.cs
- ChildTable.cs
- FlowLayoutPanel.cs
- CdpEqualityComparer.cs
- JsonServiceDocumentSerializer.cs
- DeflateStream.cs
- GridViewColumn.cs
- ElementFactory.cs
- WebPartZone.cs
- ChangeProcessor.cs
- MailAddress.cs
- CompareInfo.cs
- WindowHideOrCloseTracker.cs
- TimeIntervalCollection.cs