Example #1
0
        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");
        }
Example #2
0
        /// <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;
 }