Пример #1
0
        private EntityContainerEntitySet InferEntitySet(
            IRelationshipEnd relationshipEnd)
        {
            List <EntityContainerEntitySet> containerEntitySetList = new List <EntityContainerEntitySet>();

            foreach (EntityContainerEntitySet entitySet in this.ParentElement.EntitySets)
            {
                if (relationshipEnd.Type.IsOfType((StructuredType)entitySet.EntityType))
                {
                    containerEntitySetList.Add(entitySet);
                }
            }
            if (containerEntitySetList.Count == 1)
            {
                return(containerEntitySetList[0]);
            }
            if (containerEntitySetList.Count == 0)
            {
                this.AddError(ErrorCode.MissingExtentEntityContainerEnd, EdmSchemaErrorSeverity.Error, (object)Strings.MissingEntityContainerEnd((object)relationshipEnd.Name, (object)this.FQName));
            }
            else
            {
                this.AddError(ErrorCode.AmbiguousEntityContainerEnd, EdmSchemaErrorSeverity.Error, (object)Strings.AmbiguousEntityContainerEnd((object)relationshipEnd.Name, (object)this.FQName));
            }
            return((EntityContainerEntitySet)null);
        }
Пример #2
0
        /// <summary>
        /// For the given relationship end, find the EntityContainer Property that will work for the extent
        /// </summary>
        /// <param name="relationshipEnd">The relationship end of the RelationshipSet that needs and extent</param>
        /// <returns>Null is none could be found, or the EntityContainerProperty that is the valid extent</returns>
        private EntityContainerEntitySet InferEntitySet(IRelationshipEnd relationshipEnd)
        {
            Debug.Assert(relationshipEnd != null, "relationshipEnd parameter is null");

            List <EntityContainerEntitySet> possibleExtents = new List <EntityContainerEntitySet>();

            foreach (EntityContainerEntitySet set in ParentElement.EntitySets)
            {
                if (relationshipEnd.Type.IsOfType(set.EntityType))
                {
                    possibleExtents.Add(set);
                }
            }

            if (possibleExtents.Count == 1)
            {
                return(possibleExtents[0]);
            }
            else if (possibleExtents.Count == 0)
            {
                // no matchs
                AddError(ErrorCode.MissingExtentEntityContainerEnd, EdmSchemaErrorSeverity.Error,
                         System.Data.Entity.Strings.MissingEntityContainerEnd(relationshipEnd.Name, FQName));
            }
            else
            {
                // abmigous
                AddError(ErrorCode.AmbiguousEntityContainerEnd, EdmSchemaErrorSeverity.Error,
                         System.Data.Entity.Strings.AmbiguousEntityContainerEnd(relationshipEnd.Name, FQName));
            }

            return(null);
        }
Пример #3
0
        /// <summary>
        ///     For the given relationship end, find the EntityContainer Property that will work for the extent
        /// </summary>
        /// <param name="relationshipEnd"> The relationship end of the RelationshipSet that needs and extent </param>
        /// <returns> Null is none could be found, or the EntityContainerProperty that is the valid extent </returns>
        private EntityContainerEntitySet InferEntitySet(IRelationshipEnd relationshipEnd)
        {
            DebugCheck.NotNull(relationshipEnd);

            var possibleExtents = new List <EntityContainerEntitySet>();

            foreach (var set in ParentElement.EntitySets)
            {
                if (relationshipEnd.Type.IsOfType(set.EntityType))
                {
                    possibleExtents.Add(set);
                }
            }

            if (possibleExtents.Count == 1)
            {
                return(possibleExtents[0]);
            }
            else if (possibleExtents.Count == 0)
            {
                // no matchs
                AddError(
                    ErrorCode.MissingExtentEntityContainerEnd, EdmSchemaErrorSeverity.Error,
                    Strings.MissingEntityContainerEnd(relationshipEnd.Name, FQName));
            }
            else
            {
                // abmigous
                AddError(
                    ErrorCode.AmbiguousEntityContainerEnd, EdmSchemaErrorSeverity.Error,
                    Strings.AmbiguousEntityContainerEnd(relationshipEnd.Name, FQName));
            }

            return(null);
        }
        private static AssociationEndMember InitializeAssociationEndMember(
            AssociationType associationType,
            IRelationshipEnd end,
            EntityType endMemberType)
        {
            EdmMember            edmMember;
            AssociationEndMember associationEndMember;

            if (!associationType.Members.TryGetValue(end.Name, false, out edmMember))
            {
                associationEndMember = new AssociationEndMember(end.Name, endMemberType.GetReferenceType(), end.Multiplicity.Value);
                associationType.AddKeyMember((EdmMember)associationEndMember);
            }
            else
            {
                associationEndMember = (AssociationEndMember)edmMember;
            }
            RelationshipEnd relationshipEnd = end as RelationshipEnd;

            if (relationshipEnd != null && relationshipEnd.Documentation != null)
            {
                associationEndMember.Documentation = Converter.ConvertToDocumentation(relationshipEnd.Documentation);
            }
            return(associationEndMember);
        }
Пример #5
0
        public override IRelationship CreateRelationship(
            IRelationshipEnd rel1, IRelationshipEnd rel2)
        {
            ISheet        sheet = rel1.OwnedSheet;
            IRelationship rel   = CreateRelationship();

            rel.End1 = rel1;
            rel.End2 = rel2;
            sheet.AddRelationship(rel);
            return(rel);
        }
Пример #6
0
        protected override void AddEnd(
            IRelationshipEnd relationshipEnd,
            EntityContainerEntitySet entitySet)
        {
            EntityContainerAssociationSetEnd associationSetEnd = new EntityContainerAssociationSetEnd(this);

            associationSetEnd.Role            = relationshipEnd.Name;
            associationSetEnd.RelationshipEnd = relationshipEnd;
            associationSetEnd.EntitySet       = entitySet;
            if (associationSetEnd.EntitySet == null)
            {
                return;
            }
            this._relationshipEnds.Add(associationSetEnd.Role, associationSetEnd);
        }
Пример #7
0
        // <summary>
        // Create and add a EntityContainerEnd from the IRelationshipEnd provided
        // </summary>
        // <param name="relationshipEnd"> The relationship end of the end to add. </param>
        // <param name="entitySet"> The entitySet to associate with the relationship end. </param>
        protected override void AddEnd(IRelationshipEnd relationshipEnd, EntityContainerEntitySet entitySet)
        {
            DebugCheck.NotNull(relationshipEnd);
            Debug.Assert(!_relationshipEnds.ContainsKey(relationshipEnd.Name));
            // we expect set to be null sometimes

            var end = new EntityContainerAssociationSetEnd(this);

            end.Role            = relationshipEnd.Name;
            end.RelationshipEnd = relationshipEnd;

            end.EntitySet = entitySet;
            if (end.EntitySet != null)
            {
                _relationshipEnds.Add(end.Role, end);
            }
        }
        private static NavigationProperty ConvertToNavigationProperty(
            EntityType declaringEntityType,
            System.Data.Entity.Core.SchemaObjectModel.NavigationProperty somNavigationProperty,
            DbProviderManifest providerManifest,
            Converter.ConversionCache convertedItemCache,
            Dictionary <SchemaElement, GlobalItem> newGlobalItems)
        {
            EntityType       endMemberType   = (EntityType)Converter.LoadSchemaElement(somNavigationProperty.Type, providerManifest, convertedItemCache, newGlobalItems);
            AssociationType  associationType = (AssociationType)Converter.LoadSchemaElement((System.Data.Entity.Core.SchemaObjectModel.SchemaType)somNavigationProperty.Relationship, providerManifest, convertedItemCache, newGlobalItems);
            IRelationshipEnd end             = (IRelationshipEnd)null;

            somNavigationProperty.Relationship.TryGetEnd(somNavigationProperty.ToEnd.Name, out end);
            RelationshipMultiplicity?multiplicity1 = end.Multiplicity;
            EdmType edmType = (multiplicity1.GetValueOrDefault() != RelationshipMultiplicity.Many ? 0 : (multiplicity1.HasValue ? 1 : 0)) == 0 ? (EdmType)endMemberType : (EdmType)endMemberType.GetCollectionType();
            RelationshipMultiplicity?multiplicity2 = end.Multiplicity;
            TypeUsage typeUsage;

            if ((multiplicity2.GetValueOrDefault() != RelationshipMultiplicity.One ? 0 : (multiplicity2.HasValue ? 1 : 0)) != 0)
            {
                typeUsage = TypeUsage.Create(edmType, new FacetValues()
                {
                    Nullable = (FacetValueContainer <bool?>) new bool?(false)
                });
            }
            else
            {
                typeUsage = TypeUsage.Create(edmType);
            }
            Converter.InitializeAssociationEndMember(associationType, somNavigationProperty.ToEnd, endMemberType);
            Converter.InitializeAssociationEndMember(associationType, somNavigationProperty.FromEnd, declaringEntityType);
            NavigationProperty navigationProperty = new NavigationProperty(somNavigationProperty.Name, typeUsage);

            navigationProperty.RelationshipType = (RelationshipType)associationType;
            navigationProperty.ToEndMember      = (RelationshipEndMember)associationType.Members[somNavigationProperty.ToEnd.Name];
            navigationProperty.FromEndMember    = (RelationshipEndMember)associationType.Members[somNavigationProperty.FromEnd.Name];
            if (somNavigationProperty.Documentation != null)
            {
                navigationProperty.Documentation = Converter.ConvertToDocumentation(somNavigationProperty.Documentation);
            }
            Converter.AddOtherContent((SchemaElement)somNavigationProperty, (MetadataItem)navigationProperty);
            return(navigationProperty);
        }
Пример #9
0
 public bool TryGetEnd(string roleName, out IRelationshipEnd end)
 {
     return(_ends.TryGetEnd(roleName, out end));
 }
Пример #10
0
 protected abstract void AddEnd(IRelationshipEnd relationshipEnd, EntityContainerEntitySet entitySet);
        /// <summary>
        /// Create and add a EntityContainerEnd from the IRelationshipEnd provided
        /// </summary>
        /// <param name="relationshipEnd">The relationship end of the end to add.</param>
        /// <param name="entitySet">The entitySet to associate with the relationship end.</param>
        protected override void AddEnd(IRelationshipEnd relationshipEnd, EntityContainerEntitySet entitySet)
        {
            Debug.Assert(relationshipEnd != null);
            Debug.Assert(!_relationshipEnds.ContainsKey(relationshipEnd.Name));
            // we expect set to be null sometimes

            var end = new EntityContainerAssociationSetEnd(this);
            end.Role = relationshipEnd.Name;
            end.RelationshipEnd = relationshipEnd;

            end.EntitySet = entitySet;
            if (end.EntitySet != null)
            {
                _relationshipEnds.Add(end.Role, end);
            }
        }
Пример #12
0
        /// <summary>
        ///     Initialize the end member if its not initialized already
        /// </summary>
        /// <param name="associationType"> </param>
        /// <param name="end"> </param>
        /// <param name="endMemberType"> </param>
        private static AssociationEndMember InitializeAssociationEndMember(
            AssociationType associationType, IRelationshipEnd end,
            EntityType endMemberType)
        {
            AssociationEndMember associationEnd;

            EdmMember member;
            // make sure that the end is not initialized as of yet
            if (!associationType.Members.TryGetValue(end.Name, false /*ignoreCase*/, out member))
            {
                // Create the end member and add the operations
                associationEnd = new AssociationEndMember(
                    end.Name,
                    endMemberType.GetReferenceType(),
                    end.Multiplicity.Value);
                associationType.AddKeyMember(associationEnd);
            }
            else
            {
                associationEnd = (AssociationEndMember)member;
            }

            //Extract the optional Documentation
            var relationshipEnd = end as RelationshipEnd;

            if (relationshipEnd != null
                && (relationshipEnd.Documentation != null))
            {
                associationEnd.Documentation = ConvertToDocumentation(relationshipEnd.Documentation);
            }

            return associationEnd;
        }
Пример #13
0
        internal override void Validate()
        {
            base.Validate();
            this._principalRole.Validate();
            this._dependentRole.Validate();
            if (!ReferentialConstraint.ReadyForFurtherValidation(this._principalRole) || !ReferentialConstraint.ReadyForFurtherValidation(this._dependentRole))
            {
                return;
            }
            IRelationshipEnd end1 = this._principalRole.End;
            IRelationshipEnd end2 = this._dependentRole.End;

            if (this._principalRole.Name == this._dependentRole.Name)
            {
                this.AddError(ErrorCode.SameRoleReferredInReferentialConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.SameRoleReferredInReferentialConstraint((object)this.ParentElement.Name));
            }
            bool isKeyProperty1;
            bool areAllPropertiesNullable1;
            bool isAnyPropertyNullable1;
            bool isSubsetOfKeyProperties1;

            ReferentialConstraint.IsKeyProperty(this._dependentRole, end2.Type, out isKeyProperty1, out areAllPropertiesNullable1, out isAnyPropertyNullable1, out isSubsetOfKeyProperties1);
            bool isKeyProperty2;
            bool areAllPropertiesNullable2;
            bool isAnyPropertyNullable2;
            bool isSubsetOfKeyProperties2;

            ReferentialConstraint.IsKeyProperty(this._principalRole, end1.Type, out isKeyProperty2, out areAllPropertiesNullable2, out isAnyPropertyNullable2, out isSubsetOfKeyProperties2);
            if (!isKeyProperty2)
            {
                this.AddError(ErrorCode.InvalidPropertyInRelationshipConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.InvalidFromPropertyInRelationshipConstraint((object)this.PrincipalRole.Name, (object)end1.Type.FQName, (object)this.ParentElement.FQName));
            }
            else
            {
                bool flag = this.Schema.SchemaVersion <= 1.1;
                RelationshipMultiplicity relationshipMultiplicity1 = (flag ? (areAllPropertiesNullable2 ? 1 : 0) : (isAnyPropertyNullable2 ? 1 : 0)) != 0 ? RelationshipMultiplicity.ZeroOrOne : RelationshipMultiplicity.One;
                RelationshipMultiplicity relationshipMultiplicity2 = (flag ? (areAllPropertiesNullable1 ? 1 : 0) : (isAnyPropertyNullable1 ? 1 : 0)) != 0 ? RelationshipMultiplicity.ZeroOrOne : RelationshipMultiplicity.Many;
                IRelationshipEnd         relationshipEnd1          = end1;
                RelationshipMultiplicity?multiplicity1             = end1.Multiplicity;
                RelationshipMultiplicity?nullable1 = new RelationshipMultiplicity?(multiplicity1.HasValue ? multiplicity1.GetValueOrDefault() : relationshipMultiplicity1);
                relationshipEnd1.Multiplicity = nullable1;
                IRelationshipEnd         relationshipEnd2 = end2;
                RelationshipMultiplicity?multiplicity2    = end2.Multiplicity;
                RelationshipMultiplicity?nullable2        = new RelationshipMultiplicity?(multiplicity2.HasValue ? multiplicity2.GetValueOrDefault() : relationshipMultiplicity2);
                relationshipEnd2.Multiplicity = nullable2;
                RelationshipMultiplicity?multiplicity3 = end1.Multiplicity;
                if ((multiplicity3.GetValueOrDefault() != RelationshipMultiplicity.Many ? 0 : (multiplicity3.HasValue ? 1 : 0)) != 0)
                {
                    this.AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.InvalidMultiplicityFromRoleUpperBoundMustBeOne((object)this._principalRole.Name, (object)this.ParentElement.Name));
                }
                else
                {
                    if (areAllPropertiesNullable1)
                    {
                        RelationshipMultiplicity?multiplicity4 = end1.Multiplicity;
                        if ((multiplicity4.GetValueOrDefault() != RelationshipMultiplicity.One ? 0 : (multiplicity4.HasValue ? 1 : 0)) != 0)
                        {
                            this.AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.InvalidMultiplicityFromRoleToPropertyNullableV1((object)this._principalRole.Name, (object)this.ParentElement.Name));
                            goto label_13;
                        }
                    }
                    if (flag && !areAllPropertiesNullable1 || !flag && !isAnyPropertyNullable1)
                    {
                        RelationshipMultiplicity?multiplicity4 = end1.Multiplicity;
                        if ((multiplicity4.GetValueOrDefault() != RelationshipMultiplicity.One ? 1 : (!multiplicity4.HasValue ? 1 : 0)) != 0)
                        {
                            this.AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, EdmSchemaErrorSeverity.Error, !flag ? (object)Strings.InvalidMultiplicityFromRoleToPropertyNonNullableV2((object)this._principalRole.Name, (object)this.ParentElement.Name) : (object)Strings.InvalidMultiplicityFromRoleToPropertyNonNullableV1((object)this._principalRole.Name, (object)this.ParentElement.Name));
                        }
                    }
                }
                label_13:
                RelationshipMultiplicity? multiplicity5 = end2.Multiplicity;
                if ((multiplicity5.GetValueOrDefault() != RelationshipMultiplicity.One ? 0 : (multiplicity5.HasValue ? 1 : 0)) != 0 && this.Schema.DataModel == SchemaDataModelOption.ProviderDataModel)
                {
                    this.AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.InvalidMultiplicityToRoleLowerBoundMustBeZero((object)this._dependentRole.Name, (object)this.ParentElement.Name));
                }
                if (!isSubsetOfKeyProperties1 && !this.ParentElement.IsForeignKey && this.Schema.DataModel == SchemaDataModelOption.EntityDataModel)
                {
                    this.AddError(ErrorCode.InvalidPropertyInRelationshipConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.InvalidToPropertyInRelationshipConstraint((object)this.DependentRole.Name, (object)end2.Type.FQName, (object)this.ParentElement.FQName));
                }
                if (isKeyProperty1)
                {
                    RelationshipMultiplicity?multiplicity4 = end2.Multiplicity;
                    if ((multiplicity4.GetValueOrDefault() != RelationshipMultiplicity.Many ? 0 : (multiplicity4.HasValue ? 1 : 0)) != 0)
                    {
                        this.AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.InvalidMultiplicityToRoleUpperBoundMustBeOne((object)end2.Name, (object)this.ParentElement.Name));
                    }
                }
                else
                {
                    RelationshipMultiplicity?multiplicity4 = end2.Multiplicity;
                    if ((multiplicity4.GetValueOrDefault() != RelationshipMultiplicity.Many ? 1 : (!multiplicity4.HasValue ? 1 : 0)) != 0)
                    {
                        this.AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.InvalidMultiplicityToRoleUpperBoundMustBeMany((object)end2.Name, (object)this.ParentElement.Name));
                    }
                }
                if (this._dependentRole.RoleProperties.Count != this._principalRole.RoleProperties.Count)
                {
                    this.AddError(ErrorCode.MismatchNumberOfPropertiesInRelationshipConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.MismatchNumberOfPropertiesinRelationshipConstraint);
                }
                else
                {
                    for (int index = 0; index < this._dependentRole.RoleProperties.Count; ++index)
                    {
                        if (this._dependentRole.RoleProperties[index].Property.Type != this._principalRole.RoleProperties[index].Property.Type)
                        {
                            this.AddError(ErrorCode.TypeMismatchRelationshipConstraint, EdmSchemaErrorSeverity.Error, (object)Strings.TypeMismatchRelationshipConstraint((object)this._dependentRole.RoleProperties[index].Name, (object)this._dependentRole.End.Type.Identity, (object)this._principalRole.RoleProperties[index].Name, (object)this._principalRole.End.Type.Identity, (object)this.ParentElement.Name));
                        }
                    }
                }
            }
        }
Пример #14
0
 public bool TryGetEnd( string roleName, out IRelationshipEnd end )
 {
     return _ends.TryGetEnd( roleName, out end );
 }
Пример #15
0
 public abstract IRelationship CreateRelationship(IRelationshipEnd rel1, IRelationshipEnd rel2);
        // <summary>
        // For the given relationship end, find the EntityContainer Property that will work for the extent
        // </summary>
        // <param name="relationshipEnd"> The relationship end of the RelationshipSet that needs and extent </param>
        // <returns> Null is none could be found, or the EntityContainerProperty that is the valid extent </returns>
        private EntityContainerEntitySet InferEntitySet(IRelationshipEnd relationshipEnd)
        {
            DebugCheck.NotNull(relationshipEnd);

            var possibleExtents = new List<EntityContainerEntitySet>();
            foreach (var set in ParentElement.EntitySets)
            {
                if (relationshipEnd.Type.IsOfType(set.EntityType))
                {
                    possibleExtents.Add(set);
                }
            }

            if (possibleExtents.Count == 1)
            {
                return possibleExtents[0];
            }
            else if (possibleExtents.Count == 0)
            {
                // no matchs
                AddError(
                    ErrorCode.MissingExtentEntityContainerEnd, EdmSchemaErrorSeverity.Error,
                    Strings.MissingEntityContainerEnd(relationshipEnd.Name, FQName));
            }
            else
            {
                // abmigous
                AddError(
                    ErrorCode.AmbiguousEntityContainerEnd, EdmSchemaErrorSeverity.Error,
                    Strings.AmbiguousEntityContainerEnd(relationshipEnd.Name, FQName));
            }

            return null;
        }
Пример #17
0
        /// <summary>
        /// Validate this referential constraint
        /// </summary>
        internal override void Validate()
        {
            base.Validate();
            _principalRole.Validate();
            _dependentRole.Validate();

            if (ReadyForFurtherValidation(_principalRole) && ReadyForFurtherValidation(_dependentRole))
            {
                // Validate the to end and from end of the referential constraint
                IRelationshipEnd principalRoleEnd = _principalRole.End;
                IRelationshipEnd dependentRoleEnd = _dependentRole.End;

                bool isPrinicipalRoleKeyProperty, isDependentRoleKeyProperty;
                bool areAllPrinicipalRolePropertiesNullable, areAllDependentRolePropertiesNullable;
                bool isDependentRolePropertiesSubsetofKeyProperties, isPrinicipalRolePropertiesSubsetofKeyProperties;
                bool isAnyPrinicipalRolePropertyNullable, isAnyDependentRolePropertyNullable;

                // Validate the role name to be different
                if (_principalRole.Name == _dependentRole.Name)
                {
                    AddError(ErrorCode.SameRoleReferredInReferentialConstraint,
                             EdmSchemaErrorSeverity.Error,
                             System.Data.Entity.Strings.SameRoleReferredInReferentialConstraint(this.ParentElement.Name));
                }

                // Resolve all the property in the ToProperty attribute. Also checks whether this is nullable or not and
                // whether the properties are the keys for the type in the ToRole
                IsKeyProperty(_dependentRole, dependentRoleEnd.Type,
                              out isPrinicipalRoleKeyProperty,
                              out areAllDependentRolePropertiesNullable,
                              out isAnyDependentRolePropertyNullable,
                              out isDependentRolePropertiesSubsetofKeyProperties);

                // Resolve all the property in the ToProperty attribute. Also checks whether this is nullable or not and
                // whether the properties are the keys for the type in the ToRole
                IsKeyProperty(_principalRole, principalRoleEnd.Type,
                              out isDependentRoleKeyProperty,
                              out areAllPrinicipalRolePropertiesNullable,
                              out isAnyPrinicipalRolePropertyNullable,
                              out isPrinicipalRolePropertiesSubsetofKeyProperties);

                Debug.Assert(_principalRole.RoleProperties.Count != 0, "There should be some ref properties in Principal Role");
                Debug.Assert(_dependentRole.RoleProperties.Count != 0, "There should be some ref properties in Dependent Role");

                // The properties in the PrincipalRole must be the key of the Entity type referred to by the principal role
                if (!isDependentRoleKeyProperty)
                {
                    AddError(ErrorCode.InvalidPropertyInRelationshipConstraint,
                             EdmSchemaErrorSeverity.Error,
                             System.Data.Entity.Strings.InvalidFromPropertyInRelationshipConstraint(
                                 PrincipalRole.Name, principalRoleEnd.Type.FQName, this.ParentElement.FQName));
                }
                else
                {
                    bool v1Behavior = Schema.SchemaVersion <= XmlConstants.EdmVersionForV1_1;

                    // Determine expected multiplicities
                    RelationshipMultiplicity expectedPrincipalMultiplicity = (v1Behavior
                        ? areAllPrinicipalRolePropertiesNullable
                        : isAnyPrinicipalRolePropertyNullable)
                        ? RelationshipMultiplicity.ZeroOrOne
                        : RelationshipMultiplicity.One;
                    RelationshipMultiplicity expectedDependentMultiplicity = (v1Behavior
                        ? areAllDependentRolePropertiesNullable
                        : isAnyDependentRolePropertyNullable)
                        ? RelationshipMultiplicity.ZeroOrOne
                        : RelationshipMultiplicity.Many;
                    principalRoleEnd.Multiplicity = principalRoleEnd.Multiplicity ?? expectedPrincipalMultiplicity;
                    dependentRoleEnd.Multiplicity = dependentRoleEnd.Multiplicity ?? expectedDependentMultiplicity;

                    // Since the FromProperty must be the key of the FromRole, the FromRole cannot be '*' as multiplicity
                    // Also the lower bound of multiplicity of FromRole can be zero if and only if all the properties in
                    // ToProperties are nullable
                    // for v2+
                    if (principalRoleEnd.Multiplicity == RelationshipMultiplicity.Many)
                    {
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint,
                                 EdmSchemaErrorSeverity.Error,
                                 System.Data.Entity.Strings.InvalidMultiplicityFromRoleUpperBoundMustBeOne(_principalRole.Name, this.ParentElement.Name));
                    }
                    else if (areAllDependentRolePropertiesNullable &&
                             principalRoleEnd.Multiplicity == RelationshipMultiplicity.One)
                    {
                        string message = System.Data.Entity.Strings.InvalidMultiplicityFromRoleToPropertyNullableV1(_principalRole.Name, this.ParentElement.Name);
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint,
                                 EdmSchemaErrorSeverity.Error,
                                 message);
                    }
                    else if ((
                                 (v1Behavior && !areAllDependentRolePropertiesNullable) ||
                                 (!v1Behavior && !isAnyDependentRolePropertyNullable)
                                 ) &&
                             principalRoleEnd.Multiplicity != RelationshipMultiplicity.One)
                    {
                        string message;
                        if (v1Behavior)
                        {
                            message = System.Data.Entity.Strings.InvalidMultiplicityFromRoleToPropertyNonNullableV1(_principalRole.Name, this.ParentElement.Name);
                        }
                        else
                        {
                            message = System.Data.Entity.Strings.InvalidMultiplicityFromRoleToPropertyNonNullableV2(_principalRole.Name, this.ParentElement.Name);
                        }
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint,
                                 EdmSchemaErrorSeverity.Error,
                                 message);
                    }

                    // If the ToProperties form the key of the type in ToRole, then the upper bound of the multiplicity
                    // of the ToRole must be '1'. The lower bound must always be zero since there can be entries in the from
                    // column which are not related to child columns.
                    if (dependentRoleEnd.Multiplicity == RelationshipMultiplicity.One && Schema.DataModel == SchemaDataModelOption.ProviderDataModel)
                    {
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint,
                                 EdmSchemaErrorSeverity.Error,
                                 System.Data.Entity.Strings.InvalidMultiplicityToRoleLowerBoundMustBeZero(_dependentRole.Name, this.ParentElement.Name));
                    }

                    // Need to constrain the dependent role in CSDL to Key properties if this is not a IsForeignKey
                    // relationship.
                    if ((!isDependentRolePropertiesSubsetofKeyProperties) &&
                        (!this.ParentElement.IsForeignKey) &&
                        (Schema.DataModel == SchemaDataModelOption.EntityDataModel))
                    {
                        AddError(ErrorCode.InvalidPropertyInRelationshipConstraint,
                                 EdmSchemaErrorSeverity.Error,
                                 System.Data.Entity.Strings.InvalidToPropertyInRelationshipConstraint(
                                     DependentRole.Name, dependentRoleEnd.Type.FQName, this.ParentElement.FQName));
                    }

                    // If the ToProperty is a key property, then the upper bound must be 1 i.e. every parent (from property) can
                    // have exactly one child
                    if (isPrinicipalRoleKeyProperty)
                    {
                        if (dependentRoleEnd.Multiplicity == RelationshipMultiplicity.Many)
                        {
                            AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint,
                                     EdmSchemaErrorSeverity.Error,
                                     System.Data.Entity.Strings.InvalidMultiplicityToRoleUpperBoundMustBeOne(dependentRoleEnd.Name, this.ParentElement.Name));
                        }
                    }
                    // if the ToProperty is not the key, then the upper bound must be many i.e every parent (from property) can
                    // be related to many childs
                    else if (dependentRoleEnd.Multiplicity != RelationshipMultiplicity.Many)
                    {
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint,
                                 EdmSchemaErrorSeverity.Error,
                                 System.Data.Entity.Strings.InvalidMultiplicityToRoleUpperBoundMustBeMany(dependentRoleEnd.Name, this.ParentElement.Name));
                    }

                    if (_dependentRole.RoleProperties.Count != _principalRole.RoleProperties.Count)
                    {
                        AddError(ErrorCode.MismatchNumberOfPropertiesInRelationshipConstraint,
                                 EdmSchemaErrorSeverity.Error,
                                 System.Data.Entity.Strings.MismatchNumberOfPropertiesinRelationshipConstraint);
                    }
                    else
                    {
                        for (int i = 0; i < _dependentRole.RoleProperties.Count; i++)
                        {
                            if (_dependentRole.RoleProperties[i].Property.Type != _principalRole.RoleProperties[i].Property.Type)
                            {
                                AddError(ErrorCode.TypeMismatchRelationshipConstaint,
                                         EdmSchemaErrorSeverity.Error,
                                         System.Data.Entity.Strings.TypeMismatchRelationshipConstaint(
                                             _dependentRole.RoleProperties[i].Name,
                                             _dependentRole.End.Type.Identity,
                                             _principalRole.RoleProperties[i].Name,
                                             _principalRole.End.Type.Identity,
                                             this.ParentElement.Name
                                             ));
                            }
                        }
                    }
                }
            }
        }
 protected abstract void AddEnd(IRelationshipEnd relationshipEnd, EntityContainerEntitySet entitySet);
        /// <summary>
        /// For the given relationship end, find the EntityContainer Property that will work for the extent
        /// </summary>
        /// <param name="relationshipEnd">The relationship end of the RelationshipSet that needs and extent</param>
        /// <returns>Null is none could be found, or the EntityContainerProperty that is the valid extent</returns>
        private EntityContainerEntitySet InferEntitySet( IRelationshipEnd relationshipEnd )
        {
            Debug.Assert(relationshipEnd != null, "relationshipEnd parameter is null");

            List<EntityContainerEntitySet> possibleExtents = new List<EntityContainerEntitySet>();
            foreach ( EntityContainerEntitySet set in ParentElement.EntitySets )
            {
                if ( relationshipEnd.Type.IsOfType( set.EntityType ) )
                {
                    possibleExtents.Add( set );
                }
            }

            if ( possibleExtents.Count == 1 )
            {
                return possibleExtents[0];
            }
            else if ( possibleExtents.Count == 0 )
            {
                // no matchs
                AddError( ErrorCode.MissingExtentEntityContainerEnd, EdmSchemaErrorSeverity.Error,
                    System.Data.Entity.Strings.MissingEntityContainerEnd(relationshipEnd.Name, FQName ) );
            }
            else
            {
                // abmigous
                AddError( ErrorCode.AmbiguousEntityContainerEnd, EdmSchemaErrorSeverity.Error,
                    System.Data.Entity.Strings.AmbiguousEntityContainerEnd(relationshipEnd.Name, FQName ) );
            }

            return null;
        }