private static EntityColumnMap CreateEntityTypeElementColumnMap( DbDataReader storeDataReader, EdmType edmType, EntitySet entitySet, ColumnMap[] propertyColumnMaps, Dictionary <string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList) { EntityType entityType = (EntityType)edmType; ColumnMap[] columnMapArray = new ColumnMap[storeDataReader.FieldCount]; foreach (ColumnMap propertyColumnMap in propertyColumnMaps) { int columnPos = ((ScalarColumnMap)propertyColumnMap).ColumnPos; columnMapArray[columnPos] = propertyColumnMap; } IList <EdmMember> keyMembers = (IList <EdmMember>)entityType.KeyMembers; SimpleColumnMap[] keyColumns = new SimpleColumnMap[keyMembers.Count]; int index = 0; foreach (EdmMember member in (IEnumerable <EdmMember>)keyMembers) { int ordinalFromReader = ColumnMapFactory.GetMemberOrdinalFromReader(storeDataReader, member, edmType, renameList); ColumnMap columnMap = columnMapArray[ordinalFromReader]; keyColumns[index] = (SimpleColumnMap)columnMap; ++index; } SimpleEntityIdentity simpleEntityIdentity = new SimpleEntityIdentity(entitySet, keyColumns); return(new EntityColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, (EntityIdentity)simpleEntityIdentity)); }
internal DiscriminatedEntityIdentity( SimpleColumnMap entitySetColumn, EntitySet[] entitySetMap, SimpleColumnMap[] keyColumns) : base(keyColumns) { this.m_entitySetColumn = entitySetColumn; this.m_entitySetMap = entitySetMap; }
internal ComplexTypeColumnMap( TypeUsage type, string name, ColumnMap[] properties, SimpleColumnMap nullSentinel) : base(type, name, properties) { this.m_nullSentinel = nullSentinel; }
protected override EntityIdentity VisitEntityIdentity( DiscriminatedEntityIdentity entityIdentity, VarMap replacementVarMap) { SimpleColumnMap entitySetColumn = (SimpleColumnMap)entityIdentity.EntitySetColumnMap.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap); SimpleColumnMap[] keyColumns = this.VisitList <SimpleColumnMap>(entityIdentity.Keys, replacementVarMap); return((EntityIdentity) new DiscriminatedEntityIdentity(entitySetColumn, entityIdentity.EntitySetMap, keyColumns)); }
private readonly EntitySet[] m_entitySetMap; // optional dictionary that maps values to entitysets // <summary> // Simple constructor // </summary> // <param name="entitySetColumn"> column map representing the entityset </param> // <param name="entitySetMap"> Map from value -> the appropriate entityset </param> // <param name="keyColumns"> list of key columns </param> internal DiscriminatedEntityIdentity( SimpleColumnMap entitySetColumn, EntitySet[] entitySetMap, SimpleColumnMap[] keyColumns) : base(keyColumns) { DebugCheck.NotNull(entitySetColumn); DebugCheck.NotNull(entitySetMap); m_entitySetColumn = entitySetColumn; m_entitySetMap = entitySetMap; }
/// <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( 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]; }
/// <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( TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys) : base(type, name) { DebugCheck.NotNull(elementMap); m_element = elementMap; m_keys = keys ?? new SimpleColumnMap[0]; m_foreignKeys = foreignKeys ?? new SimpleColumnMap[0]; }
private readonly EntitySet[] m_entitySetMap; // optional dictionary that maps values to entitysets /// <summary> /// Simple constructor /// </summary> /// <param name="entitySetColumn">column map representing the entityset</param> /// <param name="entitySetMap">Map from value -> the appropriate entityset</param> /// <param name="keyColumns">list of key columns</param> internal DiscriminatedEntityIdentity( SimpleColumnMap entitySetColumn, EntitySet[] entitySetMap, SimpleColumnMap[] keyColumns) : base(keyColumns) { Debug.Assert(entitySetColumn != null, "Must specify a column map to identify the entity set"); Debug.Assert(entitySetMap != null, "Must specify a dictionary to look up entitysets"); m_entitySetColumn = entitySetColumn; m_entitySetMap = entitySetMap; }
internal override ColumnMap Visit( DiscriminatedCollectionColumnMap columnMap, VarMap replacementVarMap) { ColumnMap elementMap = columnMap.Element.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap); SimpleColumnMap discriminator = (SimpleColumnMap)columnMap.Discriminator.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap); SimpleColumnMap[] keys = this.VisitList <SimpleColumnMap>(columnMap.Keys, replacementVarMap); SimpleColumnMap[] foreignKeys = this.VisitList <SimpleColumnMap>(columnMap.ForeignKeys, replacementVarMap); return((ColumnMap) new DiscriminatedCollectionColumnMap(columnMap.Type, columnMap.Name, elementMap, keys, foreignKeys, discriminator, columnMap.DiscriminatorValue)); }
internal override ColumnMap Visit(RecordColumnMap columnMap, VarMap replacementVarMap) { SimpleColumnMap nullSentinel = columnMap.NullSentinel; if (nullSentinel != null) { nullSentinel = (SimpleColumnMap)nullSentinel.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap); } ColumnMap[] properties = this.VisitList <ColumnMap>(columnMap.Properties, replacementVarMap); return((ColumnMap) new RecordColumnMap(columnMap.Type, columnMap.Name, properties, nullSentinel)); }
internal SimplePolymorphicColumnMap( TypeUsage type, string name, ColumnMap[] baseTypeColumns, SimpleColumnMap typeDiscriminator, Dictionary <object, TypedColumnMap> typeChoices) : base(type, name, baseTypeColumns) { this.m_typedColumnMap = typeChoices; this.m_typeDiscriminator = typeDiscriminator; }
internal DiscriminatedCollectionColumnMap( TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys, SimpleColumnMap discriminator, object discriminatorValue) : base(type, name, elementMap, keys, foreignKeys) { this.m_discriminator = discriminator; this.m_discriminatorValue = discriminatorValue; }
/// <summary> /// Internal constructor /// </summary> /// <param name="type"> datatype of the column </param> /// <param name="name"> column name </param> /// <param name="baseTypeColumns"> base list of fields common to all types </param> /// <param name="typeDiscriminator"> column map for type discriminator column </param> /// <param name="typeChoices"> map from type discriminator value->columnMap </param> internal SimplePolymorphicColumnMap( TypeUsage type, string name, ColumnMap[] baseTypeColumns, SimpleColumnMap typeDiscriminator, Dictionary <object, TypedColumnMap> typeChoices) : base(type, name, baseTypeColumns) { DebugCheck.NotNull(typeDiscriminator); DebugCheck.NotNull(typeChoices); m_typedColumnMap = typeChoices; m_typeDiscriminator = typeDiscriminator; }
/// <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( TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys, SimpleColumnMap discriminator, object discriminatorValue) : base(type, name, elementMap, keys, foreignKeys) { DebugCheck.NotNull(discriminator); DebugCheck.NotNull(discriminatorValue); m_discriminator = discriminator; m_discriminatorValue = discriminatorValue; }
internal override ColumnMap Visit( SimplePolymorphicColumnMap columnMap, VarMap replacementVarMap) { SimpleColumnMap typeDiscriminator = (SimpleColumnMap)columnMap.TypeDiscriminator.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap); Dictionary <object, TypedColumnMap> typeChoices = new Dictionary <object, TypedColumnMap>(columnMap.TypeChoices.Comparer); foreach (KeyValuePair <object, TypedColumnMap> typeChoice in columnMap.TypeChoices) { TypedColumnMap typedColumnMap = (TypedColumnMap)typeChoice.Value.Accept <ColumnMap, VarMap>((ColumnMapVisitorWithResults <ColumnMap, VarMap>) this, replacementVarMap); typeChoices[typeChoice.Key] = typedColumnMap; } ColumnMap[] baseTypeColumns = this.VisitList <ColumnMap>(columnMap.Properties, replacementVarMap); return((ColumnMap) new SimplePolymorphicColumnMap(columnMap.Type, columnMap.Name, baseTypeColumns, typeDiscriminator, typeChoices)); }
// <summary> // Build the entityColumnMap from a store datareader, a type and an entitySet and // a list of properties. // </summary> private static EntityColumnMap CreateEntityTypeElementColumnMap( DbDataReader storeDataReader, EdmType edmType, EntitySet entitySet, ColumnMap[] propertyColumnMaps, Dictionary <string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList) { var 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 var ordinalToColumnMap = new ColumnMap[storeDataReader.FieldCount]; foreach (var propertyColumnMap in propertyColumnMaps) { var ordinal = ((ScalarColumnMap)propertyColumnMap).ColumnPos; ordinalToColumnMap[ordinal] = propertyColumnMap; } // Now build the list of KeyColumns; IList <EdmMember> keyMembers = entityType.KeyMembers; var keyColumns = new SimpleColumnMap[keyMembers.Count]; var keyMemberIndex = 0; foreach (var keyMember in keyMembers) { var keyOrdinal = GetMemberOrdinalFromReader(storeDataReader, keyMember, edmType, renameList); Debug.Assert(keyOrdinal >= 0, "keyMember for entity is not found by name in the data reader?"); var keyColumnMap = ordinalToColumnMap[keyOrdinal]; Debug.Assert(null != keyColumnMap, "keyMember for entity isn't in properties collection for the entity?"); keyColumns[keyMemberIndex] = (SimpleColumnMap)keyColumnMap; keyMemberIndex++; } var entityIdentity = new SimpleEntityIdentity(entitySet, keyColumns); var result = new EntityColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, entityIdentity); return(result); }
private readonly EntitySet m_entitySet; // the entity set /// <summary> /// Basic constructor. /// Note: the entitySet may be null - in which case, we are referring to /// a transient entity /// </summary> /// <param name="entitySet"> The entityset </param> /// <param name="keyColumns"> key columns of the entity </param> internal SimpleEntityIdentity(EntitySet entitySet, SimpleColumnMap[] keyColumns) : base(keyColumns) { // the entityset may be null m_entitySet = entitySet; }
// <summary> // convert MultiStreamNestOp to SingleStreamNestOp // </summary> // <remarks> // A MultiStreamNestOp is typically of the form M(D, N1, N2, ..., Nk) // where D is the driver stream, and N1, N2 etc. represent the collections. // In general, this can be converted into a SingleStreamNestOp over: // (D+ outerApply N1) AugmentedUnionAll (D+ outerApply N2) ... // Where: // D+ is D with an extra discriminator column that helps to identify // the specific collection. // AugmentedUnionAll is simply a unionAll where each branch of the // unionAll is augmented with nulls for the corresponding columns // of other tables in the branch // The simple case where there is only a single nested collection is easier // to address, and can be represented by: // MultiStreamNest(D, N1) => SingleStreamNest(OuterApply(D, N1)) // The more complex case, where there is more than one nested column, requires // quite a bit more work: // MultiStreamNest(D, X, Y,...) => SingleStreamNest(UnionAll(Project{"1", D1...Dn, X1...Xn, nY1...nYn}(OuterApply(D, X)), Project{"2", D1...Dn, nX1...nXn, Y1...Yn}(OuterApply(D, Y)), ...)) // Where: // D is the driving collection // D1...Dn are the columns from the driving collection // X is the first nested collection // X1...Xn are the columns from the first nested collection // nX1...nXn are null values for all columns from the first nested collection // Y is the second nested collection // Y1...Yn are the columns from the second nested collection // nY1...nYn are null values for all columns from the second nested collection // </remarks> private Node ConvertToSingleStreamNest( Node nestNode, Dictionary<Var, ColumnMap> varRefReplacementMap, VarList flattenedOutputVarList, out SimpleColumnMap[] parentKeyColumnMaps) { #if DEBUG var input = Dump.ToXml(nestNode); #endif //DEBUG var nestOp = (MultiStreamNestOp)nestNode.Op; // We can't convert this node to a SingleStreamNest until all it's MultiStreamNest // inputs are converted, so do that first. for (var i = 1; i < nestNode.Children.Count; i++) { var chi = nestNode.Children[i]; if (chi.Op.OpType == OpType.MultiStreamNest) { var chiCi = nestOp.CollectionInfo[i - 1]; var childFlattenedOutputVars = Command.CreateVarList(); SimpleColumnMap[] childKeyColumnMaps; nestNode.Children[i] = ConvertToSingleStreamNest( chi, varRefReplacementMap, childFlattenedOutputVars, out childKeyColumnMaps); // Now this may seem odd here, and it may look like we should have done this // inside the recursive ConvertToSingleStreamNest call above, but that call // doesn't have access to the CollectionInfo for it's parent, which is what // we need to manipulate before we enter the loop below where we try and fold // THIS nestOp nodes into a singleStreamNestOp. var childColumnMap = ColumnMapTranslator.Translate(chiCi.ColumnMap, varRefReplacementMap); var childKeys = Command.CreateVarVec(((SingleStreamNestOp)nestNode.Children[i].Op).Keys); nestOp.CollectionInfo[i - 1] = Command.CreateCollectionInfo( chiCi.CollectionVar, childColumnMap, childFlattenedOutputVars, childKeys, chiCi.SortKeys, null /*discriminatorValue*/ ); } } // Make sure that the driving node has keys defined. Otherwise we're in // trouble; we must be able to infer keys from the driving node. var drivingNode = nestNode.Child0; var drivingNodeKeys = Command.PullupKeys(drivingNode); if (drivingNodeKeys.NoKeys) { // ALMINEEV: In this case we used to wrap drivingNode into a projection that would also project Edm.NewGuid() thus giving us a synthetic key. // This solution did not work however due to a bug in SQL Server that allowed pulling non-deterministic functions above joins and applies, thus // producing incorrect results. SQL Server bug was filed in "sqlbuvsts01\Sql Server" database as #725272. // The only known path how we can get a keyless drivingNode is if // - drivingNode is over a TVF call // - TVF is declared as Collection(Row) is SSDL (the only form of TVF definitions at the moment) // - TVF is not mapped to entities // Note that if TVF is mapped to entities via function import mapping, and the user query is actually the call of the // function import, we infer keys for the TVF from the c-space entity keys and their mappings. throw new NotSupportedException(Strings.ADP_KeysRequiredForNesting); } // Get a deterministic ordering of Vars from this node. // NOTE: we're using the drivingNode's definitions, which is a VarVec so it // won't match the order of the input's columns, but the key thing is // that we use the same order for all nested children, so it's OK. var drivingNodeInfo = Command.GetExtendedNodeInfo(drivingNode); var drivingNodeVarVec = drivingNodeInfo.Definitions; var drivingNodeVars = Command.CreateVarList(drivingNodeVarVec); // Normalize all collection inputs to the nestOp. Specifically, remove any // SortOps (adding the sort keys to the postfix sortkey list). Additionally, // add a discriminatorVar to each collection child VarList discriminatorVarList; List<List<SortKey>> postfixSortKeyList; NormalizeNestOpInputs(nestOp, nestNode, out discriminatorVarList, out postfixSortKeyList); // Now build up the union-all subquery List<Dictionary<Var, Var>> varMapList; Var outputDiscriminatorVar; var unionAllNode = BuildUnionAllSubqueryForNestOp( nestOp, nestNode, drivingNodeVars, discriminatorVarList, out outputDiscriminatorVar, out varMapList); var drivingNodeVarMap = varMapList[0]; // OK. We've finally created the UnionAll over each of the project/outerApply // combinations. We know that the output columns will be: // // Discriminator, DrivingColumns, Collection1Columns, Collection2Columns, ... // // Now, rebuild the columnMaps, since all of the columns in the original column // maps are now referencing newer variables. To do that, we'll walk the list of // outputs from the unionAll, and construct new VarRefColumnMaps for each one, // and adding it to a ColumnMapPatcher, which we'll use to actually fix everything // up. // // While we're at it, we'll build a new list of top-level output columns, which // should include only the Discriminator, the columns from the driving collection, // and and one column for each of the nested collections. // Start building the flattenedOutputVarList that the top level PhysicalProjectOp // is to output. flattenedOutputVarList.AddRange(RemapVars(drivingNodeVars, drivingNodeVarMap)); var flattenedOutputVarVec = Command.CreateVarVec(flattenedOutputVarList); var nestOpOutputs = Command.CreateVarVec(flattenedOutputVarVec); // Add any adjustments to the driving nodes vars to the column map patcher foreach (var kv in drivingNodeVarMap) { if (kv.Key != kv.Value) { varRefReplacementMap[kv.Key] = new VarRefColumnMap(kv.Value); } } RemapSortKeys(nestOp.PrefixSortKeys, drivingNodeVarMap); var newPostfixSortKeys = new List<SortKey>(); var newCollectionInfoList = new List<CollectionInfo>(); // Build the discriminator column map, and ensure it's in the outputs var discriminatorColumnMap = new VarRefColumnMap(outputDiscriminatorVar); nestOpOutputs.Set(outputDiscriminatorVar); if (!flattenedOutputVarVec.IsSet(outputDiscriminatorVar)) { flattenedOutputVarList.Add(outputDiscriminatorVar); flattenedOutputVarVec.Set(outputDiscriminatorVar); } // Build the key column maps, and ensure they're in the outputs as well. var parentKeys = RemapVarVec(drivingNodeKeys.KeyVars, drivingNodeVarMap); parentKeyColumnMaps = new SimpleColumnMap[parentKeys.Count]; var index = 0; foreach (var keyVar in parentKeys) { parentKeyColumnMaps[index] = new VarRefColumnMap(keyVar); index++; if (!flattenedOutputVarVec.IsSet(keyVar)) { flattenedOutputVarList.Add(keyVar); flattenedOutputVarVec.Set(keyVar); } } // Now that we've handled the driving node, deal with each of the // nested inputs, in sequence. for (var i = 1; i < nestNode.Children.Count; i++) { var ci = nestOp.CollectionInfo[i - 1]; var postfixSortKeys = postfixSortKeyList[i]; RemapSortKeys(postfixSortKeys, varMapList[i]); newPostfixSortKeys.AddRange(postfixSortKeys); var newColumnMap = ColumnMapTranslator.Translate(ci.ColumnMap, varMapList[i]); var newFlattenedElementVars = RemapVarList(ci.FlattenedElementVars, varMapList[i]); var newCollectionKeys = RemapVarVec(ci.Keys, varMapList[i]); RemapSortKeys(ci.SortKeys, varMapList[i]); var newCollectionInfo = Command.CreateCollectionInfo( ci.CollectionVar, newColumnMap, newFlattenedElementVars, newCollectionKeys, ci.SortKeys, i); newCollectionInfoList.Add(newCollectionInfo); // For a collection Var, we add the flattened elementVars for the // collection in place of the collection Var itself, and we create // a new column map to represent all the stuff we've done. foreach (var v in newFlattenedElementVars) { if (!flattenedOutputVarVec.IsSet(v)) { flattenedOutputVarList.Add(v); flattenedOutputVarVec.Set(v); } } nestOpOutputs.Set(ci.CollectionVar); var keyColumnMapIndex = 0; var keyColumnMaps = new SimpleColumnMap[newCollectionInfo.Keys.Count]; foreach (var keyVar in newCollectionInfo.Keys) { keyColumnMaps[keyColumnMapIndex] = new VarRefColumnMap(keyVar); keyColumnMapIndex++; } var collectionColumnMap = new DiscriminatedCollectionColumnMap( TypeUtils.CreateCollectionType(newCollectionInfo.ColumnMap.Type), newCollectionInfo.ColumnMap.Name, newCollectionInfo.ColumnMap, keyColumnMaps, parentKeyColumnMaps, discriminatorColumnMap, newCollectionInfo.DiscriminatorValue ); varRefReplacementMap[ci.CollectionVar] = collectionColumnMap; } // Finally, build up the SingleStreamNest Node var newSsnOp = Command.CreateSingleStreamNestOp( parentKeys, nestOp.PrefixSortKeys, newPostfixSortKeys, nestOpOutputs, newCollectionInfoList, outputDiscriminatorVar); var newNestNode = Command.CreateNode(newSsnOp, unionAllNode); #if DEBUG var size = input.Length; // GC.KeepAlive makes FxCop Grumpy. var output = Dump.ToXml(newNestNode); #endif //DEBUG return newNestNode; }
private readonly SimpleColumnMap[] m_keys; // list of keys // <summary> // Simple constructor - gets a list of key columns // </summary> internal EntityIdentity(SimpleColumnMap[] keyColumns) { DebugCheck.NotNull(keyColumns); m_keys = keyColumns; }
private readonly SimpleColumnMap[] m_keys; // list of keys /// <summary> /// Simple constructor - gets a list of key columns /// </summary> /// <param name="keyColumns"> </param> internal EntityIdentity(SimpleColumnMap[] keyColumns) { Debug.Assert(keyColumns != null, "Must specify column maps for key columns"); m_keys = keyColumns; }
/// <summary> /// Create a column map for a ref type /// </summary> /// <param name="typeInfo"> Type information for the ref type </param> /// <param name="name"> Name of the column </param> /// <returns> Column map for the ref type </returns> private RefColumnMap CreateRefColumnMap(TypeInfo typeInfo, string name) { SimpleColumnMap entitySetIdColumnMap = null; if (typeInfo.HasEntitySetIdProperty) { entitySetIdColumnMap = CreateSimpleColumnMap( md.Helper.GetModelTypeUsage(typeInfo.EntitySetIdProperty), c_EntitySetIdColumnName); } // get the target entity type, var entityType = (md.EntityType)(TypeHelpers.GetEdmType<md.RefType>(typeInfo.Type).ElementType); // Iterate through the list of "key" properties var keyColList = new SimpleColumnMap[entityType.KeyMembers.Count]; for (var i = 0; i < keyColList.Length; ++i) { var property = entityType.KeyMembers[i]; keyColList[i] = CreateSimpleColumnMap(md.Helper.GetModelTypeUsage(property), property.Name); } // Create the entity identity var identity = CreateEntityIdentity(entityType, entitySetIdColumnMap, keyColList); var result = new RefColumnMap(typeInfo.Type, name, identity); return result; }
/// <summary> /// Constructor for a record column map /// </summary> /// <param name="type"> Datatype of this column </param> /// <param name="name"> column name </param> /// <param name="properties"> List of ColumnMaps - one for each property </param> internal RecordColumnMap(TypeUsage type, string name, ColumnMap[] properties, SimpleColumnMap nullSentinel) : base(type, name, properties) { m_nullSentinel = nullSentinel; }
/// <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) { var 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 var ordinalToColumnMap = new ColumnMap[storeDataReader.FieldCount]; foreach (var propertyColumnMap in propertyColumnMaps) { var ordinal = ((ScalarColumnMap)propertyColumnMap).ColumnPos; ordinalToColumnMap[ordinal] = propertyColumnMap; } // Now build the list of KeyColumns; IList<EdmMember> keyMembers = entityType.KeyMembers; var keyColumns = new SimpleColumnMap[keyMembers.Count]; var keyMemberIndex = 0; foreach (var keyMember in keyMembers) { var keyOrdinal = GetMemberOrdinalFromReader(storeDataReader, keyMember, edmType, renameList); Debug.Assert(keyOrdinal >= 0, "keyMember for entity is not found by name in the data reader?"); var keyColumnMap = ordinalToColumnMap[keyOrdinal]; Debug.Assert(null != keyColumnMap, "keyMember for entity isn't in properties collection for the entity?"); keyColumns[keyMemberIndex] = (SimpleColumnMap)keyColumnMap; keyMemberIndex++; } var entityIdentity = new SimpleEntityIdentity(entitySet, keyColumns); var result = new EntityColumnMap(TypeUsage.Create(edmType), edmType.Name, propertyColumnMaps, entityIdentity); return result; }
private EntityIdentity CreateEntityIdentity( md.EntityType entityType, SimpleColumnMap entitySetIdColumnMap, SimpleColumnMap[] keyColumnMaps) { // // If we have an entitysetid (and therefore, a column map for the entitysetid), // then use a discriminated entity identity; otherwise, we use a simpleentityidentity // instead // if (entitySetIdColumnMap != null) { return new DiscriminatedEntityIdentity(entitySetIdColumnMap, m_typeInfo.EntitySetIdToEntitySetMap, keyColumnMaps); } else { var entitySet = m_typeInfo.GetEntitySet(entityType); PlanCompiler.Assert( entitySet != null, "Expected non-null entitySet when no entity set ID is required. Entity type = " + entityType); return new SimpleEntityIdentity(entitySet, keyColumnMaps); } }