1 //---------------------------------------------------------------------
2 // <copyright file="TypeConstant.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
11 using System.Collections.Generic;
12 using System.Data.Mapping.ViewGeneration.CqlGeneration;
13 using System.Data.Common;
14 using System.Data.Common.CommandTrees;
15 using System.Data.Common.CommandTrees.ExpressionBuilder;
16 using System.Data.Common.Utils;
17 using System.Data.Metadata.Edm;
18 using System.Diagnostics;
21 namespace System.Data.Mapping.ViewGeneration.Structures
24 /// A constant for storing type values, e.g., a type constant is used to denote (say) a Person type, Address type, etc.
25 /// It essentially encapsulates an EDM nominal type.
27 internal sealed class TypeConstant : Constant
31 /// Creates a type constant corresponding to the <paramref name="type"/>.
33 internal TypeConstant(EdmType type)
35 Debug.Assert(type != null, "type must not be null.");
42 /// The EDM type denoted by this type constant.
44 private readonly EdmType m_edmType;
49 /// Returns the EDM type corresponding to the type constant.
51 internal EdmType EdmType
53 get { return m_edmType; }
58 internal override bool IsNull()
63 internal override bool IsNotNull()
68 internal override bool IsUndefined()
73 internal override bool HasNotNull()
78 protected override bool IsEqualTo(Constant right)
80 TypeConstant rightTypeConstant = right as TypeConstant;
81 if (rightTypeConstant == null)
85 return m_edmType == rightTypeConstant.m_edmType;
88 public override int GetHashCode()
90 if (m_edmType == null)
91 { // null type constant
96 return m_edmType.GetHashCode();
100 internal override StringBuilder AsEsql(StringBuilder builder, MemberPath outputMember, string blockAlias)
104 (refScopeEntitySet, keyMemberOutputPaths) =>
106 // Construct a scoped reference: CreateRef(CPerson1Set, NewRow(pid1, pid2), CPerson1)
107 EntityType refEntityType = (EntityType)(((RefType)outputMember.EdmType).ElementType);
108 builder.Append("CreateRef(");
109 CqlWriter.AppendEscapedQualifiedName(builder, refScopeEntitySet.EntityContainer.Name, refScopeEntitySet.Name);
110 builder.Append(", row(");
111 for (int i = 0; i < keyMemberOutputPaths.Count; ++i)
115 builder.Append(", ");
117 // Given the member, we need its aliased name
118 string fullFieldAlias = CqlWriter.GetQualifiedName(blockAlias, keyMemberOutputPaths[i].CqlFieldAlias);
119 builder.Append(fullFieldAlias);
121 builder.Append("), ");
122 CqlWriter.AppendEscapedTypeName(builder, refEntityType);
126 (membersOutputPaths) =>
128 // Construct an entity/complex/Association type in the Members order for fields: CPerson(CPerson1_Pid, CPerson1_Name)
129 CqlWriter.AppendEscapedTypeName(builder, m_edmType);
131 for (int i = 0; i < membersOutputPaths.Count; ++i)
135 builder.Append(", ");
137 // Given the member, we need its aliased name: CPerson1_Pid
138 string fullFieldAlias = CqlWriter.GetQualifiedName(blockAlias, membersOutputPaths[i].CqlFieldAlias);
139 builder.Append(fullFieldAlias);
148 internal override DbExpression AsCqt(DbExpression row, MemberPath outputMember)
150 DbExpression cqt = null;
154 (refScopeEntitySet, keyMemberOutputPaths) =>
156 // Construct a scoped reference: CreateRef(CPerson1Set, NewRow(pid1, pid2), CPerson1)
157 EntityType refEntityType = (EntityType)(((RefType)outputMember.EdmType).ElementType);
158 cqt = refScopeEntitySet.CreateRef(
160 keyMemberOutputPaths.Select(km => row.Property(km.CqlFieldAlias)));
163 (membersOutputPaths) =>
165 // Construct an entity/complex/Association type in the Members order for fields: CPerson(CPerson1_Pid, CPerson1_Name)
166 cqt = TypeUsage.Create(m_edmType).New(
167 membersOutputPaths.Select(m => row.Property(m.CqlFieldAlias)));
175 /// Given the <paramref name="outputMember"/> in the output extent view, generates a constructor expression for
176 /// <paramref name="outputMember"/>'s type, i.e, an expression of the form "Type(....)"
177 /// If <paramref name="outputMember"/> is an association end then instead of constructing an Entity or Complex type, constructs a reference.
179 private void AsCql(Action<EntitySet, IList<MemberPath>> createRef, Action<IList<MemberPath>> createType, MemberPath outputMember)
181 EntitySet refScopeEntitySet = outputMember.GetScopeOfRelationEnd();
182 if (refScopeEntitySet != null)
184 // Construct a scoped reference: CreateRef(CPerson1Set, NewRow(pid1, pid2), CPerson1)
185 EntityType entityType = refScopeEntitySet.ElementType;
186 List<MemberPath> keyMemberOutputPaths = new List<MemberPath>(entityType.KeyMembers.Select(km => new MemberPath(outputMember, km)));
187 createRef(refScopeEntitySet, keyMemberOutputPaths);
191 // Construct an entity/complex/Association type in the Members order for fields: CPerson(CPerson1_Pid, CPerson1_Name)
192 Debug.Assert(m_edmType is StructuralType, "m_edmType must be a structural type.");
193 List<MemberPath> memberOutputPaths = new List<MemberPath>();
194 foreach (EdmMember structuralMember in Helper.GetAllStructuralMembers(m_edmType))
196 memberOutputPaths.Add(new MemberPath(outputMember, structuralMember));
198 createType(memberOutputPaths);
202 internal override string ToUserString()
204 StringBuilder builder = new StringBuilder();
205 ToCompactString(builder);
206 return builder.ToString();
209 internal override void ToCompactString(StringBuilder builder)
211 builder.Append(m_edmType.Name);