ReferentialConstraint.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / EntityModel / SchemaObjectModel / ReferentialConstraint.cs / 2 / ReferentialConstraint.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml;
using System.Data; 
using System.Data.Metadata.Edm;
 
namespace System.Data.EntityModel.SchemaObjectModel 
{
    ///  
    /// Represents an referential constraint on a relationship
    /// 
    internal sealed class ReferentialConstraint : SchemaElement
    { 
        private const char KEY_DELIMITER = ' ';
        private ReferentialConstraintRoleElement _principalRole; 
        private ReferentialConstraintRoleElement _dependentRole; 

        ///  
        /// construct a Referential constraint
        /// 
        /// 
        public ReferentialConstraint(Relationship relationship) 
            : base(relationship)
        { 
        } 

        ///  
        /// Validate this referential constraint
        /// 
        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, isPrinicipalRolePropertiesNullable, isDependentRolePropertiesNullable, isDependentRolePropertiesSubsetofKeyProperties, isPrinicipalRolePropertiesSubsetofKeyProperties; 
 
                // 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 isDependentRolePropertiesNullable, 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 isPrinicipalRolePropertiesNullable, 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
                { 
                    // 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
                    if (principalRoleEnd.Multiplicity == RelationshipMultiplicity.Many) 
                    {
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, 
                                 EdmSchemaErrorSeverity.Error, 
                                 System.Data.Entity.Strings.InvalidMultiplicityFromRoleUpperBoundMustBeOne(_principalRole.Name, this.ParentElement.Name));
                    } 
                    else if (isDependentRolePropertiesNullable && principalRoleEnd.Multiplicity == RelationshipMultiplicity.One)
                    {
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint,
                                 EdmSchemaErrorSeverity.Error, 
                                 System.Data.Entity.Strings.InvalidMultiplicityFromRoleToPropertyNullable(_principalRole.Name, this.ParentElement.Name));
                    } 
                    else if (!isDependentRolePropertiesNullable && principalRoleEnd.Multiplicity != RelationshipMultiplicity.One) 
                    {
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, 
                                 EdmSchemaErrorSeverity.Error,
                                 System.Data.Entity.Strings.InvalidMultiplicityFromRoleToPropertyNonNullable(_principalRole.Name, this.ParentElement.Name));
                    }
 
                    // 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 ((!isDependentRolePropertiesSubsetofKeyProperties) && 
                        (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, 
                                                       _principalRole.RoleProperties[i].Name));
                            } 
                        }
                    }
                }
            } 
        }
 
        private static bool ReadyForFurtherValidation(ReferentialConstraintRoleElement role) 
        {
            if (role == null) 
                return false;

            if(role.End == null)
                return false; 

            if(role.RoleProperties.Count == 0) 
                return false; 

            foreach(PropertyRefElement propRef in role.RoleProperties) 
            {
                if(propRef.Property == null)
                    return false;
            } 

            return true; 
        } 

        ///  
        /// Resolves the given property names to the property in the item
        /// Also checks whether the properties form the key for the given type and whether all the properties are nullable or not
        /// 
        ///  
        /// 
        ///  
        ///  
        /// 
        private static void IsKeyProperty(ReferentialConstraintRoleElement roleElement, SchemaEntityType itemType, out bool isKeyProperty, out bool isNullable, 
                                   out bool isSubsetOfKeyProperties)
        {
            isKeyProperty = true;
            isNullable = true; 
            isSubsetOfKeyProperties = true;
 
            if (itemType.KeyProperties.Count != roleElement.RoleProperties.Count) 
            {
                isKeyProperty = false; 
            }

            // Checking that ToProperties must be the key properties in the entity type referred by the ToRole
            for (int i = 0; i < roleElement.RoleProperties.Count; i++) 
            {
                // Once we find that the properties in the constraint are not a subset of the 
                // Key, one need not search for it every time 
                if (isSubsetOfKeyProperties)
                { 

                    bool foundKeyProperty = false;

                    // All properties that are defined in ToProperties must be the key property on the entity type 
                    for (int j = 0; j < itemType.KeyProperties.Count; j++)
                    { 
                        if (itemType.KeyProperties[j].Property == roleElement.RoleProperties[i].Property) 
                        {
                            foundKeyProperty = true; 
                            break;
                        }
                    }
 
                    if (!foundKeyProperty)
                    { 
                        isKeyProperty = false; 
                        isSubsetOfKeyProperties = false;
                    } 
                }

                isNullable &= roleElement.RoleProperties[i].Property.Nullable;
            } 
        }
 
        protected override bool HandleAttribute(XmlReader reader) 
        {
            return false; 
        }

        protected override bool HandleElement(XmlReader reader)
        { 
            if (base.HandleElement(reader))
            { 
                return true; 
            }
            else if (CanHandleElement(reader, XmlConstants.PrincipalRole)) 
            {
                HandleReferentialConstraintPrincipalRoleElement(reader);
                return true;
            } 
            else if (CanHandleElement(reader, XmlConstants.DependentRole))
            { 
                HandleReferentialConstraintDependentRoleElement(reader); 
                return true;
            } 

            return false;
        }
 
        internal void HandleReferentialConstraintPrincipalRoleElement(XmlReader reader)
        { 
            _principalRole = new ReferentialConstraintRoleElement(this); 
            _principalRole.Parse(reader);
        } 

        internal void HandleReferentialConstraintDependentRoleElement(XmlReader reader)
        {
            _dependentRole = new ReferentialConstraintRoleElement(this); 
            _dependentRole.Parse(reader);
        } 
 
        internal override void ResolveTopLevelNames()
        { 
            _dependentRole.ResolveTopLevelNames();

            _principalRole.ResolveTopLevelNames();
        } 

        ///  
        /// The parent element as an IRelationship 
        /// 
        internal new IRelationship ParentElement 
        {
            get
            {
                return (IRelationship)(base.ParentElement); 
            }
        } 
 
        internal ReferentialConstraintRoleElement PrincipalRole
        { 
            get
            {
                return _principalRole;
            } 
        }
 
        internal ReferentialConstraintRoleElement DependentRole 
        {
            get 
            {
                return _dependentRole;
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml;
using System.Data; 
using System.Data.Metadata.Edm;
 
namespace System.Data.EntityModel.SchemaObjectModel 
{
    ///  
    /// Represents an referential constraint on a relationship
    /// 
    internal sealed class ReferentialConstraint : SchemaElement
    { 
        private const char KEY_DELIMITER = ' ';
        private ReferentialConstraintRoleElement _principalRole; 
        private ReferentialConstraintRoleElement _dependentRole; 

        ///  
        /// construct a Referential constraint
        /// 
        /// 
        public ReferentialConstraint(Relationship relationship) 
            : base(relationship)
        { 
        } 

        ///  
        /// Validate this referential constraint
        /// 
        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, isPrinicipalRolePropertiesNullable, isDependentRolePropertiesNullable, isDependentRolePropertiesSubsetofKeyProperties, isPrinicipalRolePropertiesSubsetofKeyProperties; 
 
                // 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 isDependentRolePropertiesNullable, 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 isPrinicipalRolePropertiesNullable, 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
                { 
                    // 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
                    if (principalRoleEnd.Multiplicity == RelationshipMultiplicity.Many) 
                    {
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, 
                                 EdmSchemaErrorSeverity.Error, 
                                 System.Data.Entity.Strings.InvalidMultiplicityFromRoleUpperBoundMustBeOne(_principalRole.Name, this.ParentElement.Name));
                    } 
                    else if (isDependentRolePropertiesNullable && principalRoleEnd.Multiplicity == RelationshipMultiplicity.One)
                    {
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint,
                                 EdmSchemaErrorSeverity.Error, 
                                 System.Data.Entity.Strings.InvalidMultiplicityFromRoleToPropertyNullable(_principalRole.Name, this.ParentElement.Name));
                    } 
                    else if (!isDependentRolePropertiesNullable && principalRoleEnd.Multiplicity != RelationshipMultiplicity.One) 
                    {
                        AddError(ErrorCode.InvalidMultiplicityInRoleInRelationshipConstraint, 
                                 EdmSchemaErrorSeverity.Error,
                                 System.Data.Entity.Strings.InvalidMultiplicityFromRoleToPropertyNonNullable(_principalRole.Name, this.ParentElement.Name));
                    }
 
                    // 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 ((!isDependentRolePropertiesSubsetofKeyProperties) && 
                        (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, 
                                                       _principalRole.RoleProperties[i].Name));
                            } 
                        }
                    }
                }
            } 
        }
 
        private static bool ReadyForFurtherValidation(ReferentialConstraintRoleElement role) 
        {
            if (role == null) 
                return false;

            if(role.End == null)
                return false; 

            if(role.RoleProperties.Count == 0) 
                return false; 

            foreach(PropertyRefElement propRef in role.RoleProperties) 
            {
                if(propRef.Property == null)
                    return false;
            } 

            return true; 
        } 

        ///  
        /// Resolves the given property names to the property in the item
        /// Also checks whether the properties form the key for the given type and whether all the properties are nullable or not
        /// 
        ///  
        /// 
        ///  
        ///  
        /// 
        private static void IsKeyProperty(ReferentialConstraintRoleElement roleElement, SchemaEntityType itemType, out bool isKeyProperty, out bool isNullable, 
                                   out bool isSubsetOfKeyProperties)
        {
            isKeyProperty = true;
            isNullable = true; 
            isSubsetOfKeyProperties = true;
 
            if (itemType.KeyProperties.Count != roleElement.RoleProperties.Count) 
            {
                isKeyProperty = false; 
            }

            // Checking that ToProperties must be the key properties in the entity type referred by the ToRole
            for (int i = 0; i < roleElement.RoleProperties.Count; i++) 
            {
                // Once we find that the properties in the constraint are not a subset of the 
                // Key, one need not search for it every time 
                if (isSubsetOfKeyProperties)
                { 

                    bool foundKeyProperty = false;

                    // All properties that are defined in ToProperties must be the key property on the entity type 
                    for (int j = 0; j < itemType.KeyProperties.Count; j++)
                    { 
                        if (itemType.KeyProperties[j].Property == roleElement.RoleProperties[i].Property) 
                        {
                            foundKeyProperty = true; 
                            break;
                        }
                    }
 
                    if (!foundKeyProperty)
                    { 
                        isKeyProperty = false; 
                        isSubsetOfKeyProperties = false;
                    } 
                }

                isNullable &= roleElement.RoleProperties[i].Property.Nullable;
            } 
        }
 
        protected override bool HandleAttribute(XmlReader reader) 
        {
            return false; 
        }

        protected override bool HandleElement(XmlReader reader)
        { 
            if (base.HandleElement(reader))
            { 
                return true; 
            }
            else if (CanHandleElement(reader, XmlConstants.PrincipalRole)) 
            {
                HandleReferentialConstraintPrincipalRoleElement(reader);
                return true;
            } 
            else if (CanHandleElement(reader, XmlConstants.DependentRole))
            { 
                HandleReferentialConstraintDependentRoleElement(reader); 
                return true;
            } 

            return false;
        }
 
        internal void HandleReferentialConstraintPrincipalRoleElement(XmlReader reader)
        { 
            _principalRole = new ReferentialConstraintRoleElement(this); 
            _principalRole.Parse(reader);
        } 

        internal void HandleReferentialConstraintDependentRoleElement(XmlReader reader)
        {
            _dependentRole = new ReferentialConstraintRoleElement(this); 
            _dependentRole.Parse(reader);
        } 
 
        internal override void ResolveTopLevelNames()
        { 
            _dependentRole.ResolveTopLevelNames();

            _principalRole.ResolveTopLevelNames();
        } 

        ///  
        /// The parent element as an IRelationship 
        /// 
        internal new IRelationship ParentElement 
        {
            get
            {
                return (IRelationship)(base.ParentElement); 
            }
        } 
 
        internal ReferentialConstraintRoleElement PrincipalRole
        { 
            get
            {
                return _principalRole;
            } 
        }
 
        internal ReferentialConstraintRoleElement DependentRole 
        {
            get 
            {
                return _dependentRole;
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK