/// <summary> /// basic constructor /// </summary> /// <param name="outputVars">List of outputs from this Op</param> /// <param name="columnMap">column map that describes the result to be shaped</param> internal PhysicalProjectOp(VarList outputVars, SimpleCollectionColumnMap columnMap) : this() { Debug.Assert(null != columnMap, "null columnMap?"); m_outputVars = outputVars; m_columnMap = columnMap; }
/// <summary> /// SimpleCollectionColumnMap /// </summary> /// <param name="columnMap"></param> /// <param name="replacementVarMap"></param> /// <returns></returns> internal override ColumnMap Visit(SimpleCollectionColumnMap columnMap, VarMap replacementVarMap) { ColumnMap newElementColumnMap = columnMap.Element.Accept(this, replacementVarMap); SimpleColumnMap[] newKeys = VisitList(columnMap.Keys, replacementVarMap); SimpleColumnMap[] newForeignKeys = VisitList(columnMap.ForeignKeys, replacementVarMap); return(new SimpleCollectionColumnMap(columnMap.Type, columnMap.Name, newElementColumnMap, newKeys, newForeignKeys)); }
internal virtual void Visit(SimpleCollectionColumnMap columnMap, TArgType arg) { foreach (SimpleColumnMap fk in columnMap.ForeignKeys) { fk.Accept(this, arg); } foreach (SimpleColumnMap k in columnMap.Keys) { k.Accept(this, arg); } columnMap.Element.Accept(this, arg); }
/// <summary> /// Creates a column map for the given reader and function mapping. /// </summary> internal static CollectionColumnMap CreateFunctionImportStructuralTypeColumnMap(DbDataReader storeDataReader, FunctionImportMappingNonComposable mapping, int resultSetIndex, EntitySet entitySet, StructuralType baseStructuralType) { FunctionImportStructuralTypeMappingKB resultMapping = mapping.GetResultMapping(resultSetIndex); Debug.Assert(resultMapping != null); if (resultMapping.NormalizedEntityTypeMappings.Count == 0) // no explicit mapping; use default non-polymorphic reader { // if there is no mapping, create default mapping to root entity type or complex type Debug.Assert(!baseStructuralType.Abstract, "mapping loader must verify abstract types have explicit mapping"); return(CreateColumnMapFromReaderAndType(storeDataReader, baseStructuralType, entitySet, resultMapping.ReturnTypeColumnsRenameMapping)); } // the section below deals with the polymorphic entity type mapping for return type EntityType baseEntityType = baseStructuralType as EntityType; Debug.Assert(null != baseEntityType, "We should have entity type here"); // Generate column maps for all discriminators ScalarColumnMap[] discriminatorColumns = CreateDiscriminatorColumnMaps(storeDataReader, mapping, resultSetIndex); // Generate default maps for all mapped entity types var mappedEntityTypes = new HashSet <EntityType>(resultMapping.MappedEntityTypes); mappedEntityTypes.Add(baseEntityType); // make sure the base type is represented Dictionary <EntityType, TypedColumnMap> typeChoices = new Dictionary <EntityType, TypedColumnMap>(mappedEntityTypes.Count); ColumnMap[] baseTypeColumnMaps = null; foreach (EntityType entityType in mappedEntityTypes) { ColumnMap[] propertyColumnMaps = GetColumnMapsForType(storeDataReader, entityType, resultMapping.ReturnTypeColumnsRenameMapping); EntityColumnMap entityColumnMap = CreateEntityTypeElementColumnMap(storeDataReader, entityType, entitySet, propertyColumnMaps, resultMapping.ReturnTypeColumnsRenameMapping); if (!entityType.Abstract) { typeChoices.Add(entityType, entityColumnMap); } if (entityType == baseStructuralType) { baseTypeColumnMaps = propertyColumnMaps; } } // 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. MultipleDiscriminatorPolymorphicColumnMap polymorphicMap = new MultipleDiscriminatorPolymorphicColumnMap(TypeUsage.Create(baseStructuralType), baseStructuralType.Name, baseTypeColumnMaps, discriminatorColumns, typeChoices, (object[] discriminatorValues) => mapping.Discriminate(discriminatorValues, resultSetIndex)); CollectionColumnMap collection = new SimpleCollectionColumnMap(baseStructuralType.GetCollectionType().TypeUsage, baseStructuralType.Name, polymorphicMap, null, null); return(collection); }
/// <summary> /// Copies a PhysicalProjectOp /// </summary> /// <param name="op"></param> /// <param name="n"></param> /// <returns></returns> public override Node Visit(PhysicalProjectOp op, Node n) { // Visit the Node's children and map their Vars List <Node> children = ProcessChildren(n); // Copy the ProjectOp's VarSet VarList newVarList = Copy(op.Outputs); SimpleCollectionColumnMap newColumnMap = Copy(op.ColumnMap) as SimpleCollectionColumnMap; Debug.Assert(newColumnMap != null, "Coping of a physical project's columnMap did not return a SimpleCollectionColumnMap"); // Create a new ProjectOp based on the copied VarSet PhysicalProjectOp newProject = m_destCmd.CreatePhysicalProjectOp(newVarList, newColumnMap); // Return a new Node that references the copied ProjectOp and has the copied child Nodes as its children return(m_destCmd.CreateNode(newProject, children)); }
/// <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> /// 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); }
/// <summary> /// SimpleCollectionColumnMap /// </summary> /// <param name="columnMap"></param> /// <param name="dumper"></param> /// <returns></returns> internal override void Visit(SimpleCollectionColumnMap columnMap, Dump dumper) { using (new AutoXml(dumper, "SimpleCollection", GetAttributes(columnMap))) { DumpCollection(columnMap, dumper); } }
internal abstract TResultType Visit(SimpleCollectionColumnMap columnMap, TArgType arg);