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> /// Get the relationship set with the given name /// </summary> /// <param name="name">name of the relationship set to look up for</param> /// <param name="ignoreCase">true if you want to do a case-insensitive lookup</param> /// <param name="relationshipSet">out parameter that will have the result</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException">if name argument is null</exception> public bool TryGetRelationshipSetByName(string name, bool ignoreCase, out RelationshipSet relationshipSet) { EntityUtil.CheckArgumentNull(name, "name"); EntitySetBase baseEntitySet = null; relationshipSet = null; if (this.BaseEntitySets.TryGetValue(name, ignoreCase, out baseEntitySet)) { if (Helper.IsRelationshipSet(baseEntitySet)) { relationshipSet = (RelationshipSet)baseEntitySet; return(true); } } return(false); }
/// <summary> /// Builds up a join between the relationshipset and the entityset corresponding to its toEnd. In essence, /// we produce /// SELECT r, e /// FROM RS as r, OFTYPE(ES, T) as e /// WHERE r.ToEnd = Ref(e) /// /// "T" is the entity type of the toEnd of the relationship. /// </summary> /// <param name="relSet">the relationshipset</param> /// <param name="end">the toEnd of the relationship</param> /// <param name="rsVar">the var representing the relationship instance ("r") in the output subquery</param> /// <param name="esVar">the var representing the entity instance ("e") in the output subquery</param> /// <returns>the join subquery described above</returns> private Node BuildJoinForNavProperty( RelationshipSet relSet, RelationshipEndMember end, out Var rsVar, out Var esVar) { var entitySet = FindTargetEntitySet(relSet, end); // // Build out the ScanTable ops for the relationshipset and the entityset. Add the // var asTableNode = BuildOfTypeTable(relSet, null, out rsVar); var esTableNode = BuildOfTypeTable(entitySet, TypeHelpers.GetElementTypeUsage(end.TypeUsage), out esVar); // // Build up a join between the entityset and the associationset; join on the to-end // var joinPredicate = m_command.BuildComparison( OpType.EQ, m_command.CreateNode(m_command.CreateGetEntityRefOp(end.TypeUsage), m_command.CreateNode(m_command.CreateVarRefOp(esVar))), m_command.CreateNode(m_command.CreatePropertyOp(end), m_command.CreateNode(m_command.CreateVarRefOp(rsVar))) ); var joinNode = m_command.CreateNode( m_command.CreateInnerJoinOp(), asTableNode, esTableNode, joinPredicate); return joinNode; }
private static EntitySetBase FindTargetEntitySet(RelationshipSet relationshipSet, RelationshipEndMember targetEnd) { EntitySetBase entitySet = null; var associationSet = (AssociationSet)relationshipSet; // find the corresponding entityset entitySet = null; foreach (var e in associationSet.AssociationSetEnds) { if (e.CorrespondingAssociationEndMember.EdmEquals(targetEnd)) { entitySet = e.EntitySet; break; } } PlanCompiler.Assert( entitySet != null, "Could not find entity set for relationship set " + relationshipSet + ";association end " + targetEnd); return entitySet; }
/// <summary> /// Get the relationship set with the given name /// </summary> /// <param name="name">name of the relationship set to look up for</param> /// <param name="ignoreCase">true if you want to do a case-insensitive lookup</param> /// <param name="relationshipSet">out parameter that will have the result</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException">if name argument is null</exception> public bool TryGetRelationshipSetByName(string name, bool ignoreCase, out RelationshipSet relationshipSet) { EntityUtil.CheckArgumentNull(name, "name"); EntitySetBase baseEntitySet = null; relationshipSet = null; if (this.BaseEntitySets.TryGetValue(name, ignoreCase, out baseEntitySet)) { if (Helper.IsRelationshipSet(baseEntitySet)) { relationshipSet = (RelationshipSet)baseEntitySet; return true; } } return false; }
/// <summary> /// Get the relationship set with the given name /// </summary> /// <param name="name">name of the relationship set to look up for</param> /// <param name="ignoreCase">true if you want to do a case-insensitive lookup</param> /// <param name="relationshipSet">out parameter that will have the result</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException">if name argument is null</exception> public bool TryGetRelationshipSetByName(string name, bool ignoreCase, out RelationshipSet relationshipSet) { //Contract.Requires(name != null); EntitySetBase baseEntitySet = null; relationshipSet = null; if (BaseEntitySets.TryGetValue(name, ignoreCase, out baseEntitySet)) { if (Helper.IsRelationshipSet(baseEntitySet)) { relationshipSet = (RelationshipSet)baseEntitySet; return true; } } return false; }