/// <summary> /// Constructor /// </summary> /// <param name="type">datatype of column</param> /// <param name="name">column name</param> /// <param name="elementMap">column map for collection element</param> /// <param name="keys">List of keys</param> /// <param name="foreignKeys">List of foreign keys</param> internal CollectionColumnMap(md.TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys) : base(type, name) { Debug.Assert(elementMap != null, "Must specify column map for element"); m_element = elementMap; m_keys = keys ?? new SimpleColumnMap[0]; m_foreignKeys = foreignKeys ?? new SimpleColumnMap[0]; }
internal CollectionInfo(Var collectionVar, ColumnMap columnMap, VarList flattenedElementVars, VarVec keys, List <InternalTrees.SortKey> sortKeys, object discriminatorValue) { m_collectionVar = collectionVar; m_columnMap = columnMap; m_flattenedElementVars = flattenedElementVars; m_keys = keys; m_sortKeys = sortKeys; m_discriminatorValue = discriminatorValue; }
/// <summary> /// Internal constructor /// </summary> /// <param name="type">Column datatype</param> /// <param name="name">column name</param> /// <param name="elementMap">column map for collection element</param> /// <param name="keys">Keys for the collection</param> /// <param name="foreignKeys">Foreign keys for the collection</param> /// <param name="discriminator">Discriminator column map</param> /// <param name="discriminatorValue">Discriminator value</param> internal DiscriminatedCollectionColumnMap(md.TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys, SimpleColumnMap discriminator, object discriminatorValue) : base(type, name, elementMap, keys, foreignKeys) { Debug.Assert(discriminator != null, "Must specify a column map for the collection discriminator"); Debug.Assert(discriminatorValue != null, "Must specify a discriminator value"); m_discriminator = discriminator; m_discriminatorValue = discriminatorValue; }
internal virtual void Visit(ComplexTypeColumnMap columnMap, TArgType arg) { ColumnMap nullSentinel = columnMap.NullSentinel; if (null != nullSentinel) { nullSentinel.Accept(this, arg); } foreach (ColumnMap p in columnMap.Properties) { p.Accept(this, arg); } }
private Node VisitNestOp(Node n) { NestBaseOp op = n.Op as NestBaseOp; SingleStreamNestOp ssnOp = op as SingleStreamNestOp; Debug.Assert(op != null); // Visit the Node's children and map their Vars List <Node> newChildren = ProcessChildren(n); Var newDiscriminator = null; if (ssnOp != null) { newDiscriminator = GetMappedVar(ssnOp.Discriminator); } List <CollectionInfo> newCollectionInfoList = new List <CollectionInfo>(); foreach (CollectionInfo ci in op.CollectionInfo) { ColumnMap newColumnMap = Copy(ci.ColumnMap); Var newCollectionVar = m_destCmd.CreateComputedVar(ci.CollectionVar.Type); SetMappedVar(ci.CollectionVar, newCollectionVar); VarList newFlattendElementVars = Copy(ci.FlattenedElementVars); VarVec newKeys = Copy(ci.Keys); List <SortKey> newSortKeys = Copy(ci.SortKeys); CollectionInfo newCollectionInfo = Command.CreateCollectionInfo(newCollectionVar, newColumnMap, newFlattendElementVars, newKeys, newSortKeys, ci.DiscriminatorValue); newCollectionInfoList.Add(newCollectionInfo); } VarVec newOutputs = Copy(op.Outputs); NestBaseOp newOp = null; List <SortKey> newPrefixSortKeys = Copy(op.PrefixSortKeys); if (ssnOp != null) { VarVec newKeys = Copy(ssnOp.Keys); // Copy the SortOp's SortKeys List <SortKey> newPostfixSortKeys = Copy(ssnOp.PostfixSortKeys); newOp = m_destCmd.CreateSingleStreamNestOp(newKeys, newPrefixSortKeys, newPostfixSortKeys, newOutputs, newCollectionInfoList, newDiscriminator); } else { newOp = m_destCmd.CreateMultiStreamNestOp(newPrefixSortKeys, newOutputs, newCollectionInfoList); } return(m_destCmd.CreateNode(newOp, newChildren)); }
static internal string ToXml(ColumnMap columnMap) { MemoryStream stream = new MemoryStream(); using (Dump dumper = new Dump(stream)) { // Just in case the node we're provided doesn't dump as XML, we'll always stick // an XML wrapper around it -- this happens when we're dumping scalarOps, for // example, and it's unfortunate if you can't debug them using a dump... using (new AutoXml(dumper, "columnMap")) { columnMap.Accept(ColumnMapDumper.Instance, dumper); } } return(DefaultEncoding.GetString(stream.ToArray())); }
/// <summary> /// Build the entityColumnMap from a store datareader, a type and an entitySet and /// a list ofproperties. /// </summary> /// <param name="storeDataReader"></param> /// <param name="edmType"></param> /// <param name="entitySet"></param> /// <param name="propertyColumnMaps"></param> /// <returns></returns> private static EntityColumnMap CreateEntityTypeElementColumnMap( DbDataReader storeDataReader, EdmType edmType, EntitySet entitySet, ColumnMap[] propertyColumnMaps, Dictionary <string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList) { EntityType entityType = (EntityType)edmType; // The tricky part here is // that the KeyColumns list must point at the same ColumnMap(s) that // the properties list points to, so we build a quick array of // ColumnMap(s) that are indexed by their ordinal; then we can walk // the list of keyMembers, and find the ordinal in the reader, and // pick the same ColumnMap for it. // Build the ordinal -> ColumnMap index ColumnMap[] ordinalToColumnMap = new ColumnMap[storeDataReader.FieldCount]; foreach (ColumnMap propertyColumnMap in propertyColumnMaps) { int ordinal = ((ScalarColumnMap)propertyColumnMap).ColumnPos; ordinalToColumnMap[ordinal] = propertyColumnMap; } // Now build the list of KeyColumns; IList <EdmMember> keyMembers = entityType.KeyMembers; SimpleColumnMap[] keyColumns = new SimpleColumnMap[keyMembers.Count]; int keyMemberIndex = 0; foreach (EdmMember keyMember in keyMembers) { int keyOrdinal = GetMemberOrdinalFromReader(storeDataReader, keyMember, edmType, renameList); Debug.Assert(keyOrdinal >= 0, "keyMember for entity is not found by name in the data reader?"); ColumnMap keyColumnMap = ordinalToColumnMap[keyOrdinal]; Debug.Assert(null != keyColumnMap, "keyMember for entity isn't in properties collection for the entity?"); keyColumns[keyMemberIndex] = (SimpleColumnMap)keyColumnMap; keyMemberIndex++; } SimpleEntityIdentity entityIdentity = new SimpleEntityIdentity(entitySet, keyColumns); EntityColumnMap result = new EntityColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, entityIdentity); return(result); }
/// <summary> /// Build the collectionColumnMap from a store datareader, a type and an entitySet. /// </summary> /// <param name="storeDataReader"></param> /// <param name="edmType"></param> /// <param name="entitySet"></param> /// <returns></returns> internal static CollectionColumnMap CreateColumnMapFromReaderAndType(DbDataReader storeDataReader, EdmType edmType, EntitySet entitySet, Dictionary <string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList) { Debug.Assert(Helper.IsEntityType(edmType) || null == entitySet, "The specified non-null EntitySet is incompatible with the EDM type specified."); // Next, build the ColumnMap directly from the edmType and entitySet provided. ColumnMap[] propertyColumnMaps = GetColumnMapsForType(storeDataReader, edmType, renameList); ColumnMap elementColumnMap = null; // NOTE: We don't have a null sentinel here, because the stored proc won't // return one anyway; we'll just presume the data's always there. if (Helper.IsRowType(edmType)) { elementColumnMap = new RecordColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, null); } else if (Helper.IsComplexType(edmType)) { elementColumnMap = new ComplexTypeColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, null); } else if (Helper.IsScalarType(edmType)) { if (storeDataReader.FieldCount != 1) { throw EntityUtil.CommandExecutionDataReaderFieldCountForScalarType(); } elementColumnMap = new ScalarColumnMap(TypeUsage.Create(edmType), edmType.Name, 0, 0); } else if (Helper.IsEntityType(edmType)) { elementColumnMap = CreateEntityTypeElementColumnMap(storeDataReader, edmType, entitySet, propertyColumnMaps, null /*renameList*/); } else { Debug.Assert(false, "unexpected edmType?"); } CollectionColumnMap collection = new SimpleCollectionColumnMap(edmType.GetCollectionType().TypeUsage, edmType.Name, elementColumnMap, null, null); return(collection); }
/// <summary> /// For a given edmType, build an array of scalarColumnMaps that map to the columns /// in the store datareader provided. Note that we're hooking things up by name, not /// by ordinal position. /// </summary> /// <param name="storeDataReader"></param> /// <param name="edmType"></param> /// <returns></returns> private static ColumnMap[] GetColumnMapsForType(DbDataReader storeDataReader, EdmType edmType, Dictionary <string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList) { // First get the list of properties; NOTE: we need to hook up the column by name, // not by position. IBaseList <EdmMember> members = TypeHelpers.GetAllStructuralMembers(edmType); ColumnMap[] propertyColumnMaps = new ColumnMap[members.Count]; int index = 0; foreach (EdmMember member in members) { if (!Helper.IsScalarType(member.TypeUsage.EdmType)) { throw EntityUtil.InvalidOperation(Strings.ADP_InvalidDataReaderUnableToMaterializeNonScalarType(member.Name, member.TypeUsage.EdmType.FullName)); } int ordinal = GetMemberOrdinalFromReader(storeDataReader, member, edmType, renameList); propertyColumnMaps[index] = new ScalarColumnMap(member.TypeUsage, member.Name, 0, ordinal); index++; } return(propertyColumnMaps); }
/// <summary> /// Requires: a public type with a public, default constructor. Returns a column map initializing the type /// and all properties of the type with a public setter taking a primitive type and having a corresponding /// column in the reader. /// </summary> internal static CollectionColumnMap CreateColumnMapFromReaderAndClrType(DbDataReader reader, Type type, MetadataWorkspace workspace) { Debug.Assert(null != reader); Debug.Assert(null != type); Debug.Assert(null != workspace); // we require a default constructor ConstructorInfo constructor = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null); if (type.IsAbstract || (null == constructor && !type.IsValueType)) { throw EntityUtil.InvalidOperation( Strings.ObjectContext_InvalidTypeForStoreQuery(type)); } // build a LINQ expression used by result assembly to create results var memberInfo = new List <Tuple <MemberAssignment, int, EdmProperty> >(); foreach (PropertyInfo prop in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { // for enums unwrap the type if nullable var propertyUnderlyingType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; Type propType = propertyUnderlyingType.IsEnum ? propertyUnderlyingType.GetEnumUnderlyingType() : prop.PropertyType; EdmType modelType; int ordinal; if (TryGetColumnOrdinalFromReader(reader, prop.Name, out ordinal) && MetadataHelper.TryDetermineCSpaceModelType(propType, workspace, out modelType) && (Helper.IsScalarType(modelType)) && prop.CanWrite && prop.GetIndexParameters().Length == 0 && null != prop.GetSetMethod(/* nonPublic */ true)) { memberInfo.Add(Tuple.Create( Expression.Bind(prop, Expression.Parameter(prop.PropertyType, "placeholder")), ordinal, new EdmProperty(prop.Name, TypeUsage.Create(modelType)))); } } // initialize members in the order in which they appear in the reader MemberInfo[] members = new MemberInfo[memberInfo.Count]; MemberBinding[] memberBindings = new MemberBinding[memberInfo.Count]; ColumnMap[] propertyMaps = new ColumnMap[memberInfo.Count]; EdmProperty[] modelProperties = new EdmProperty[memberInfo.Count]; int i = 0; foreach (var memberGroup in memberInfo.GroupBy(tuple => tuple.Item2).OrderBy(tuple => tuple.Key)) { // make sure that a single column isn't contributing to multiple properties if (memberGroup.Count() != 1) { throw EntityUtil.InvalidOperation(Strings.ObjectContext_TwoPropertiesMappedToSameColumn( reader.GetName(memberGroup.Key), String.Join(", ", memberGroup.Select(tuple => tuple.Item3.Name).ToArray()))); } var member = memberGroup.Single(); MemberAssignment assignment = member.Item1; int ordinal = member.Item2; EdmProperty modelProp = member.Item3; members[i] = assignment.Member; memberBindings[i] = assignment; propertyMaps[i] = new ScalarColumnMap(modelProp.TypeUsage, modelProp.Name, 0, ordinal); modelProperties[i] = modelProp; i++; } NewExpression newExpr = null == constructor?Expression.New(type) : Expression.New(constructor); MemberInitExpression init = Expression.MemberInit(newExpr, memberBindings); InitializerMetadata initMetadata = InitializerMetadata.CreateProjectionInitializer( (EdmItemCollection)workspace.GetItemCollection(DataSpace.CSpace), init, members); // column map (a collection of rows with InitializerMetadata markup) RowType rowType = new RowType(modelProperties, initMetadata); RecordColumnMap rowMap = new RecordColumnMap(TypeUsage.Create(rowType), "DefaultTypeProjection", propertyMaps, null); CollectionColumnMap collectionMap = new SimpleCollectionColumnMap(rowType.GetCollectionType().TypeUsage, rowType.Name, rowMap, null, null); return(collectionMap); }
private ColumnMap Copy(ColumnMap columnMap) { return(ColumnMapCopier.Copy(columnMap, m_varMap)); }