internal ForeignKeyConstraint(md.RelationshipType relType, md.RelationshipSet relationshipSet, md.ReferentialConstraint constraint) { md.AssociationSet assocSet = relationshipSet as md.AssociationSet; md.AssociationEndMember fromEnd = constraint.FromRole as md.AssociationEndMember; md.AssociationEndMember toEnd = constraint.ToRole as md.AssociationEndMember; // Currently only Associations are supported if (null == assocSet || null == fromEnd || null == toEnd) { throw EntityUtil.NotSupported(); } m_constraint = constraint; md.EntitySet parent = System.Data.Common.Utils.MetadataHelper.GetEntitySetAtEnd(assocSet, fromEnd); // relationshipSet.GetRelationshipEndExtent(constraint.FromRole); md.EntitySet child = System.Data.Common.Utils.MetadataHelper.GetEntitySetAtEnd(assocSet, toEnd); // relationshipSet.GetRelationshipEndExtent(constraint.ToRole); m_extentPair = new ExtentPair(parent, child); m_childKeys = new List <string>(); foreach (md.EdmProperty prop in constraint.ToProperties) { m_childKeys.Add(prop.Name); } m_parentKeys = new List <string>(); foreach (md.EdmProperty prop in constraint.FromProperties) { m_parentKeys.Add(prop.Name); } PlanCompiler.Assert((md.RelationshipMultiplicity.ZeroOrOne == fromEnd.RelationshipMultiplicity || md.RelationshipMultiplicity.One == fromEnd.RelationshipMultiplicity), "from-end of relationship constraint cannot have multiplicity greater than 1"); }
/// <summary> /// Load all relationships in this entity container /// </summary> /// <param name="entityContainer"></param> internal void LoadRelationships(md.EntityContainer entityContainer) { // Check to see if I've already loaded information for this entity container if (m_entityContainerMap.ContainsKey(entityContainer)) { return; } // Load all relationships from this entitycontainer foreach (md.EntitySetBase e in entityContainer.BaseEntitySets) { md.RelationshipSet relationshipSet = e as md.RelationshipSet; if (relationshipSet == null) { continue; } // Relationship sets can only contain relationships md.RelationshipType relationshipType = (md.RelationshipType)relationshipSet.ElementType; md.AssociationType assocType = relationshipType as md.AssociationType; // // Handle only binary Association relationships for now // if (null == assocType || !IsBinary(relationshipType)) { continue; } foreach (md.ReferentialConstraint constraint in assocType.ReferentialConstraints) { List <ForeignKeyConstraint> fkConstraintList; ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint(relationshipType, relationshipSet, constraint); if (!m_parentChildRelationships.TryGetValue(fkConstraint.Pair, out fkConstraintList)) { fkConstraintList = new List <ForeignKeyConstraint>(); m_parentChildRelationships[fkConstraint.Pair] = fkConstraintList; } // // Theoretically, we can have more than one fk constraint between // the 2 tables (though, it is unlikely) // fkConstraintList.Add(fkConstraint); } } // Mark this entity container as already loaded m_entityContainerMap[entityContainer] = entityContainer; }
/// <summary> /// Is this relationship a binary relationship (ie) does it have exactly 2 end points? /// /// This should ideally be a method supported by RelationType itself /// </summary> /// <param name="relationshipType"></param> /// <returns>true, if this is a binary relationship</returns> private static bool IsBinary(md.RelationshipType relationshipType) { int endCount = 0; foreach (md.EdmMember member in relationshipType.Members) { if (member is md.RelationshipEndMember) { endCount++; if (endCount > 2) { return(false); } } } return(endCount == 2); }
/// <summary> /// Add any rel properties that are induced by the supplied relationship /// </summary> /// <param name="relationshipType">the relationship</param> private void ProcessRelationship(RelationshipType relationshipType) { var associationType = relationshipType as AssociationType; if (associationType == null) { return; } // Handle only binary associations if (associationType.AssociationEndMembers.Count != 2) { return; } var end0 = associationType.AssociationEndMembers[0]; var end1 = associationType.AssociationEndMembers[1]; AddRelProperty(associationType, end0, end1); AddRelProperty(associationType, end1, end0); }
/// <summary> /// Get the list of relationshipsets that can hold instances of the given relationshiptype /// /// We identify the list of relationshipsets in the current list of entitycontainers that are /// of the given type. Since we don't yet support relationshiptype subtyping, this is a little /// easier than the entity version /// </summary> /// <param name="relType">the relationship type to look for</param> /// <returns>the list of relevant relationshipsets</returns> private List<RelationshipSet> GetRelationshipSets(RelationshipType relType) { var relSets = new List<RelationshipSet>(); foreach (var entityContainer in m_referencedEntityContainers) { foreach (var set in entityContainer.BaseEntitySets) { var relSet = set as RelationshipSet; if (relSet != null && relSet.ElementType.Equals(relType)) { relSets.Add(relSet); } } } return relSets; }
internal RelProperty(RelationshipType relationshipType, RelationshipEndMember fromEnd, RelationshipEndMember toEnd) { m_relationshipType = relationshipType; m_fromEnd = fromEnd; m_toEnd = toEnd; }
/// <summary> /// The constructor for constructing the RelationshipSet with a given name and an relationship type /// </summary> /// <param name="name">The name of the RelationshipSet</param> /// <param name="schema">The db schema</param> /// <param name="table">The db table</param> /// <param name="definingQuery">The provider specific query that should be used to retrieve the EntitySet</param> /// <param name="relationshipType">The entity type of the entities that this entity set type contains</param> /// <exception cref="System.ArgumentNullException">Thrown if the argument name or entityType is null</exception> internal RelationshipSet(string name, string schema, string table, string definingQuery, RelationshipType relationshipType) : base(name, schema, table, definingQuery, relationshipType) { }
/// <summary> /// Dumps the specified Relation metadata instance /// </summary> /// <param name="type">The Relation metadata to dump</param> internal void Dump(RelationshipType type) { Begin( "RelationshipType", "Namespace", type.NamespaceName, "Name", type.Name ); End("RelationshipType"); }
/// <summary> /// Dumps the specified Relation metadata instance with the specified decoration /// </summary> /// <param name="type">The Relation metadata to dump</param> /// <param name="name">The decorating block name</param> internal void Dump(RelationshipType type, string name) { Begin(name); Dump(type); End(name); }
protected override void Visit(RelationshipType relationshipType) { base.Visit(relationshipType); }
protected virtual void Visit(RelationshipType relationshipType) { // switching node, will not be add to the seen list if (relationshipType == null) { return; } #region Inner data visit switch (relationshipType.BuiltInTypeKind) { case BuiltInTypeKind.AssociationType: Visit((AssociationType)relationshipType); break; default: Debug.Fail(String.Format(CultureInfo.InvariantCulture, "Found type '{0}', did we add a new type?", relationshipType.BuiltInTypeKind)); break; } #endregion }
/// <summary> /// The constructor for constructing the RelationshipSet with a given name and an relationship type /// </summary> /// <param name="name">The name of the RelationshipSet</param> /// <param name="schema">The db schema</param> /// <param name="table">The db table</param> /// <param name="definingQuery">The provider specific query that should be used to retrieve the EntitySet</param> /// <param name="relationshipType">The entity type of the entities that this entity set type contains</param> /// <exception cref="System.ArgumentNullException">Thrown if the argument name or entityType is null</exception> internal RelationshipSet(string name, string schema, string table, string definingQuery, RelationshipType relationshipType) : base(name, schema, table, definingQuery, relationshipType) { }