EntityContainer.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 / EntityContainer.cs / 3 / EntityContainer.cs

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

using System; 
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Xml; 
using System.Diagnostics;
using System.Data; 
using System.Data.Metadata.Edm; 
using System.Data.Common.Utils;
using System.Data.Entity; 
using System.Linq;

namespace System.Data.EntityModel.SchemaObjectModel
{ 
    /// 
    /// Represents an EntityContainer element. 
    ///  
    [System.Diagnostics.DebuggerDisplay("Name={Name}")]
    internal sealed class EntityContainer : SchemaType 
    {
        #region Instance Fields

        private SchemaElementLookUpTable _members; 
        private ISchemaElementLookUpTable _entitySets;
        private ISchemaElementLookUpTable _relationshipSets; 
        private ISchemaElementLookUpTable _functionImports; 
        private string _unresolvedExtendedEntityContainerName;
        private EntityContainer _entityContainerGettingExtended; 
        private bool _isAlreadyValidated;
        private bool _isAlreadyResolved;

        #endregion 

        #region Constructors 
 
        /// 
        /// Constructs an EntityContainer 
        /// 
        /// Reference to the schema element.
        public EntityContainer(Schema parentElement)
            : base(parentElement) 
        {
        } 
 
        #endregion
 
        #region Properties, Methods, Events & Delegates

        /// 
        /// 
        /// 
        SchemaElementLookUpTable Members 
        { 
            get
            { 
                if (_members == null)
                {
                    _members = new SchemaElementLookUpTable();
                } 
                return _members;
            } 
        } 

        ///  
        ///
        /// 
        public ISchemaElementLookUpTable EntitySets
        { 
            get
            { 
                if (_entitySets == null) 
                {
                    _entitySets = new FilteredSchemaElementLookUpTable(Members); 
                }
                return _entitySets;
            }
        } 

        ///  
        /// 
        /// 
        public ISchemaElementLookUpTable RelationshipSets 
        {
            get
            {
                if (_relationshipSets == null) 
                {
                    _relationshipSets = new FilteredSchemaElementLookUpTable(Members); 
                } 
                return _relationshipSets;
            } 
        }

        /// 
        /// 
        /// 
        public ISchemaElementLookUpTable FunctionImports 
        { 
            get
            { 
                if (_functionImports == null)
                {
                    _functionImports = new FilteredSchemaElementLookUpTable(Members);
                } 
                return _functionImports;
            } 
        } 

        ///  
        ///
        /// 
        public EntityContainer ExtendingEntityContainer
        { 
            get
            { 
                return _entityContainerGettingExtended; 
            }
        } 

        protected override bool HandleAttribute(XmlReader reader)
        {
            if (base.HandleAttribute(reader)) 
            {
                return true; 
            } 
            else if (CanHandleAttribute(reader, XmlConstants.Extends))
            { 
                HandleExtendsAttribute(reader);
                return true;
            }
 
            return false;
        } 
 
        protected override bool HandleElement(XmlReader reader)
        { 
            if (base.HandleElement(reader))
            {
                return true;
            } 
            else if (CanHandleElement(reader, XmlConstants.EntitySet))
            { 
                HandleEntitySetElement(reader); 
                return true;
            } 
            else if (CanHandleElement(reader, XmlConstants.AssociationSet))
            {
                HandleAssociationSetElement(reader);
                return true; 
            }
            else if (CanHandleElement(reader, XmlConstants.FunctionImport)) 
            { 
                HandleFunctionImport(reader);
                return true; 
            }

            return false;
        } 

        private void HandleEntitySetElement(XmlReader reader) 
        { 
            Debug.Assert(reader != null);
            EntityContainerEntitySet set = new EntityContainerEntitySet(this); 
            set.Parse(reader);
            Members.Add(set, true, Strings.DuplicateEntityContainerMemberName);
        }
 
        private void HandleAssociationSetElement(XmlReader reader)
        { 
            Debug.Assert(reader != null); 
            EntityContainerAssociationSet set = new EntityContainerAssociationSet(this);
            set.Parse(reader); 
            Members.Add(set, true, Strings.DuplicateEntityContainerMemberName);
        }

        private void HandleFunctionImport(XmlReader reader) 
        {
            Debug.Assert(null != reader); 
            FunctionImportElement functionImport = new FunctionImportElement(this); 
            functionImport.Parse(reader);
            Members.Add(functionImport, true, Strings.DuplicateEntityContainerMemberName); 
        }

        /// 
        /// 
        /// 
        ///  
        private void HandleExtendsAttribute(XmlReader reader) 
        {
            _unresolvedExtendedEntityContainerName = HandleUndottedNameAttribute(reader, _unresolvedExtendedEntityContainerName); 
        }

        /// 
        /// Resolves the names to element references. 
        /// 
        internal override void ResolveTopLevelNames() 
        { 
            if (!_isAlreadyResolved)
            { 
                base.ResolveTopLevelNames();

                SchemaType extendingEntityContainer;
                // If this entity container extends some other entity container, we should validate the entity container name. 
                if (!String.IsNullOrEmpty(_unresolvedExtendedEntityContainerName))
                { 
                    if (_unresolvedExtendedEntityContainerName == this.Name) 
                    {
                        AddError(ErrorCode.EntityContainerCannotExtendItself, EdmSchemaErrorSeverity.Error, 
                            System.Data.Entity.Strings.EntityContainerCannotExtendItself(this.Name));
                    }
                    else if (!Schema.SchemaManager.TryResolveType(null, _unresolvedExtendedEntityContainerName, out extendingEntityContainer))
                    { 
                        AddError(ErrorCode.InvalidEntityContainerNameInExtends, EdmSchemaErrorSeverity.Error,
                                System.Data.Entity.Strings.InvalidEntityContainerNameInExtends(_unresolvedExtendedEntityContainerName)); 
                    } 
                    else
                    { 
                        _entityContainerGettingExtended = (EntityContainer)extendingEntityContainer;

                        // Once you have successfully resolved the entity container, then you should call ResolveNames on the
                        // extending entity containers as well. This is because we will need to look up the chain for resolving 
                        // entity set names, since there might be association sets/ function imports that refer to entity sets
                        // belonging in extended entity containers 
                        _entityContainerGettingExtended.ResolveTopLevelNames(); 
                    }
                } 

                foreach (SchemaElement element in Members)
                {
                    element.ResolveTopLevelNames(); 
                }
 
                _isAlreadyResolved = true; 
            }
        } 

        internal override void ResolveSecondLevelNames()
        {
            base.ResolveSecondLevelNames(); 

            foreach (SchemaElement element in Members) 
            { 
                element.ResolveSecondLevelNames();
            } 
        }

        /// 
        /// Do all validation for this element here, and delegate to all sub elements 
        /// 
        internal override void Validate() 
        { 
            // Now before we clone all the entity sets from the entity container that this entity container is extending,
            // we need to make sure that the entity container that is getting extended is already validated. since it might 
            // be extending some other entity container, and we might want to populate this entity container, before
            // it gets extended
            if (!_isAlreadyValidated)
            { 
                base.Validate();
 
                // If this entity container extends some other entity container, then we should add all the 
                // sets and function imports from that entity container to this entity container
                if (this.ExtendingEntityContainer != null) 
                {
                    // Call Validate on the entity container that is getting extended, so that its entity set
                    // is populated
                    this.ExtendingEntityContainer.Validate(); 

                    foreach (SchemaElement element in this.ExtendingEntityContainer.Members) 
                    { 
                        AddErrorKind error = this.Members.TryAdd(element.Clone(this));
                        DuplicateOrEquivalentMemberNameWhileExtendingEntityContainer(element, error); 
                    }
                }

                HashSet tableKeys = new HashSet(); 

                foreach (SchemaElement element in Members) 
                { 
                    EntityContainerEntitySet entitySet = element as EntityContainerEntitySet;
                    if (entitySet != null && Schema.DataModel == SchemaDataModelOption.ProviderDataModel) 
                    {
                        CheckForDuplicateTableMapping(tableKeys, entitySet);
                    }
                    element.Validate(); 
                }
 
                ValidateRelationshipSetHaveUniqueEnds(); 

                ValidateOnlyBaseEntitySetTypeDefinesConcurrency(); 

                // Set isAlreadyValidated to true
                _isAlreadyValidated = true;
            } 
        }
 
        ///  
        /// Find the EntityContainerEntitySet in the same EntityContainer with the name from the extent
        /// attribute 
        /// 
        /// the name of the EntityContainerProperty to find
        /// The EntityContainerProperty it found or null if it fails to find it
        internal EntityContainerEntitySet FindEntitySet(string name) 
        {
            EntityContainer current = this; 
            while(current != null) 
            {
                foreach (EntityContainerEntitySet set in current.EntitySets) 
                {
                    if (Utils.CompareNames(set.Name, name) == 0)
                    {
                        return set; 
                    }
                } 
 
                current = current.ExtendingEntityContainer;
            } 

            return null;
        }
 
        private void DuplicateOrEquivalentMemberNameWhileExtendingEntityContainer(SchemaElement schemaElement,
            AddErrorKind error) 
        { 
            Debug.Assert(error != AddErrorKind.MissingNameError, "Since entity container members are already resolved, name must never be empty");
            Debug.Assert(this.ExtendingEntityContainer != null, "ExtendingEntityContainer must not be null"); 

            if (error != AddErrorKind.Succeeded)
            {
                Debug.Assert(error == AddErrorKind.DuplicateNameError, "Error must be duplicate name error"); 
                schemaElement.AddError(ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error,
                            System.Data.Entity.Strings.DuplicateMemberNameInExtendedEntityContainer( 
                                schemaElement.Name, ExtendingEntityContainer.Name, this.Name)); 
            }
        } 

        private void ValidateOnlyBaseEntitySetTypeDefinesConcurrency()
        {
            // collect all the base entitySet types 
            Dictionary baseEntitySetTypes = new Dictionary();
            foreach (SchemaElement element in Members) 
            { 
                EntityContainerEntitySet entitySet = element as EntityContainerEntitySet;
                if (entitySet != null && !baseEntitySetTypes.ContainsKey(entitySet.EntityType)) 
                {
                    baseEntitySetTypes.Add(entitySet.EntityType, entitySet);
                }
            } 

            // look through each type in this schema and see if it is derived from a base 
            // type if it is then see if it has some "new" Concurrency fields 
            foreach (SchemaType type in Schema.SchemaTypes)
            { 
                SchemaEntityType itemType = type as SchemaEntityType;
                if (itemType != null)
                {
                    EntityContainerEntitySet set; 
                    if (TypeIsSubTypeOf(itemType, baseEntitySetTypes, out set) &&
                       TypeDefinesNewConcurrencyProperties(itemType)) 
                    { 
                        AddError(ErrorCode.ConcurrencyRedefinedOnSubTypeOfEntitySetType,
                            EdmSchemaErrorSeverity.Error, 
                            System.Data.Entity.Strings.ConcurrencyRedefinedOnSubTypeOfEntitySetType(itemType.FQName, set.EntityType.FQName, set.FQName));
                    }
                }
            } 

        } 
 
        /// 
        /// Validates that if there are more than one relationship set referring to the same type, each role of the relationship type 
        /// never refers to the same entity set
        /// 
        private void ValidateRelationshipSetHaveUniqueEnds()
        { 
            // Contains the list of ends that have been visited and validated
            List alreadyValidatedEnds = new List(); 
            bool error = true; 

            foreach (EntityContainerRelationshipSet currentSet in this.RelationshipSets) 
            {
                foreach (EntityContainerRelationshipSetEnd currentSetEnd in currentSet.Ends)
                {
                    error = false; 
                    foreach (EntityContainerRelationshipSetEnd alreadyValidatedEnd in alreadyValidatedEnds)
                    { 
                        if (AreRelationshipEndsEqual(alreadyValidatedEnd, currentSetEnd)) 
                        {
                            AddError(ErrorCode.SimilarRelationshipEnd, 
                                     EdmSchemaErrorSeverity.Error,
                                     System.Data.Entity.Strings.SimilarRelationshipEnd(alreadyValidatedEnd.Name, alreadyValidatedEnd.ParentElement.FQName,
                                                         currentSetEnd.ParentElement.FQName, alreadyValidatedEnd.EntitySet.FQName, this.FQName));
                            error = true; 
                            break;
                        } 
                    } 
                    if (!error)
                    { 
                        alreadyValidatedEnds.Add(currentSetEnd);
                    }
                }
            } 
        }
 
        private static bool TypeIsSubTypeOf(SchemaEntityType itemType, Dictionary baseEntitySetTypes, out EntityContainerEntitySet set) 
        {
            if (itemType.IsTypeHierarchyRoot) 
            {
                // can't be a sub type if we are a base type
                set = null;
                return false; 
            }
 
            // walk up the hierarchy looking for a base that is the base type of an entityset 
            for (SchemaEntityType baseType = itemType.BaseType as SchemaEntityType; baseType != null; baseType = baseType.BaseType as SchemaEntityType)
            { 
                if (baseEntitySetTypes.ContainsKey(baseType))
                {
                    set = baseEntitySetTypes[baseType];
                    return true; 
                }
            } 
 
            set = null;
            return false; 
        }

        private static bool TypeDefinesNewConcurrencyProperties(SchemaEntityType itemType)
        { 
            foreach (StructuredProperty property in itemType.Properties)
            { 
                if (property.Type is ScalarType && MetadataHelper.GetConcurrencyMode(property.TypeUsage) != ConcurrencyMode.None) 
                {
                    return true; 
                }
            }

            return false; 
        }
 
        ///  
        /// Return the fully qualified name for entity container. Since EntityContainer no longer lives in a schema,
        /// the FQName should be same as that of the Name 
        /// 
        public override string FQName
        {
            get 
            {
                return this.Name; 
            } 
        }
 
        /// 
        ///
        /// 
        public override string Identity 
        {
            get 
            { 
                return Name;
            } 
        }

        /// 
        /// Adds a child EntitySet's tableKey (Schema/Table combination) to the validation collection 
        /// This is used to validate that no child EntitySets share a Schema.Table combination
        ///  
        private void CheckForDuplicateTableMapping(HashSet tableKeys, EntityContainerEntitySet entitySet) 
        {
            string schema; 
            string table;

            if (String.IsNullOrEmpty(entitySet.DbSchema))
            { 
                // if there is no specified DbSchema, use the parent EntityContainer's name
                schema = this.Name; 
            } 
            else
            { 
                schema = entitySet.DbSchema;
            }

 
            if (String.IsNullOrEmpty(entitySet.Table))
            { 
                // if there is no specified Table, use the EntitySet's name 
                table = entitySet.Name;
            } 
            else
            {
                table = entitySet.Table;
            } 

            // create a key using the DbSchema and Table 
            string tableKey = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}.{1}", schema, table); 
            if (entitySet.DefiningQuery != null)
            { 
                // don't consider the schema name for defining queries, because
                // we can't say for sure that it is the same as the entity container
                // so in this example
                // 
                // 
                //    
                //     Select col1 from dbi.ByVal 
                //   
                //    
                //   ...
                //
                // ByVal and ByVal1 should not conflict in our check
                tableKey = entitySet.Name; 
            }
 
            bool alreadyExisted = !tableKeys.Add(tableKey); 
            if (alreadyExisted)
            { 
                entitySet.AddError(ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.DuplicateEntitySetTable(entitySet.Name, schema, table));
            }
        }
 
        /// 
        /// Returns true if the given two ends are similar - the relationship type that this ends belongs to is the same 
        /// and the entity set refered by the ends are same and they have the same role name 
        /// 
        ///  
        /// 
        /// 
        private static bool AreRelationshipEndsEqual(EntityContainerRelationshipSetEnd left, EntityContainerRelationshipSetEnd right)
        { 
            Debug.Assert(left.ParentElement.ParentElement == right.ParentElement.ParentElement, "both end should belong to the same entity container");
 
            if (object.ReferenceEquals(left.EntitySet, right.EntitySet) && 
                object.ReferenceEquals(left.ParentElement.Relationship, right.ParentElement.Relationship) &&
                left.Name == right.Name) 
            {
                return true;
            }
 
            return false;
        } 
        #endregion 
    }
 
}

// 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;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Xml; 
using System.Diagnostics;
using System.Data; 
using System.Data.Metadata.Edm; 
using System.Data.Common.Utils;
using System.Data.Entity; 
using System.Linq;

namespace System.Data.EntityModel.SchemaObjectModel
{ 
    /// 
    /// Represents an EntityContainer element. 
    ///  
    [System.Diagnostics.DebuggerDisplay("Name={Name}")]
    internal sealed class EntityContainer : SchemaType 
    {
        #region Instance Fields

        private SchemaElementLookUpTable _members; 
        private ISchemaElementLookUpTable _entitySets;
        private ISchemaElementLookUpTable _relationshipSets; 
        private ISchemaElementLookUpTable _functionImports; 
        private string _unresolvedExtendedEntityContainerName;
        private EntityContainer _entityContainerGettingExtended; 
        private bool _isAlreadyValidated;
        private bool _isAlreadyResolved;

        #endregion 

        #region Constructors 
 
        /// 
        /// Constructs an EntityContainer 
        /// 
        /// Reference to the schema element.
        public EntityContainer(Schema parentElement)
            : base(parentElement) 
        {
        } 
 
        #endregion
 
        #region Properties, Methods, Events & Delegates

        /// 
        /// 
        /// 
        SchemaElementLookUpTable Members 
        { 
            get
            { 
                if (_members == null)
                {
                    _members = new SchemaElementLookUpTable();
                } 
                return _members;
            } 
        } 

        ///  
        ///
        /// 
        public ISchemaElementLookUpTable EntitySets
        { 
            get
            { 
                if (_entitySets == null) 
                {
                    _entitySets = new FilteredSchemaElementLookUpTable(Members); 
                }
                return _entitySets;
            }
        } 

        ///  
        /// 
        /// 
        public ISchemaElementLookUpTable RelationshipSets 
        {
            get
            {
                if (_relationshipSets == null) 
                {
                    _relationshipSets = new FilteredSchemaElementLookUpTable(Members); 
                } 
                return _relationshipSets;
            } 
        }

        /// 
        /// 
        /// 
        public ISchemaElementLookUpTable FunctionImports 
        { 
            get
            { 
                if (_functionImports == null)
                {
                    _functionImports = new FilteredSchemaElementLookUpTable(Members);
                } 
                return _functionImports;
            } 
        } 

        ///  
        ///
        /// 
        public EntityContainer ExtendingEntityContainer
        { 
            get
            { 
                return _entityContainerGettingExtended; 
            }
        } 

        protected override bool HandleAttribute(XmlReader reader)
        {
            if (base.HandleAttribute(reader)) 
            {
                return true; 
            } 
            else if (CanHandleAttribute(reader, XmlConstants.Extends))
            { 
                HandleExtendsAttribute(reader);
                return true;
            }
 
            return false;
        } 
 
        protected override bool HandleElement(XmlReader reader)
        { 
            if (base.HandleElement(reader))
            {
                return true;
            } 
            else if (CanHandleElement(reader, XmlConstants.EntitySet))
            { 
                HandleEntitySetElement(reader); 
                return true;
            } 
            else if (CanHandleElement(reader, XmlConstants.AssociationSet))
            {
                HandleAssociationSetElement(reader);
                return true; 
            }
            else if (CanHandleElement(reader, XmlConstants.FunctionImport)) 
            { 
                HandleFunctionImport(reader);
                return true; 
            }

            return false;
        } 

        private void HandleEntitySetElement(XmlReader reader) 
        { 
            Debug.Assert(reader != null);
            EntityContainerEntitySet set = new EntityContainerEntitySet(this); 
            set.Parse(reader);
            Members.Add(set, true, Strings.DuplicateEntityContainerMemberName);
        }
 
        private void HandleAssociationSetElement(XmlReader reader)
        { 
            Debug.Assert(reader != null); 
            EntityContainerAssociationSet set = new EntityContainerAssociationSet(this);
            set.Parse(reader); 
            Members.Add(set, true, Strings.DuplicateEntityContainerMemberName);
        }

        private void HandleFunctionImport(XmlReader reader) 
        {
            Debug.Assert(null != reader); 
            FunctionImportElement functionImport = new FunctionImportElement(this); 
            functionImport.Parse(reader);
            Members.Add(functionImport, true, Strings.DuplicateEntityContainerMemberName); 
        }

        /// 
        /// 
        /// 
        ///  
        private void HandleExtendsAttribute(XmlReader reader) 
        {
            _unresolvedExtendedEntityContainerName = HandleUndottedNameAttribute(reader, _unresolvedExtendedEntityContainerName); 
        }

        /// 
        /// Resolves the names to element references. 
        /// 
        internal override void ResolveTopLevelNames() 
        { 
            if (!_isAlreadyResolved)
            { 
                base.ResolveTopLevelNames();

                SchemaType extendingEntityContainer;
                // If this entity container extends some other entity container, we should validate the entity container name. 
                if (!String.IsNullOrEmpty(_unresolvedExtendedEntityContainerName))
                { 
                    if (_unresolvedExtendedEntityContainerName == this.Name) 
                    {
                        AddError(ErrorCode.EntityContainerCannotExtendItself, EdmSchemaErrorSeverity.Error, 
                            System.Data.Entity.Strings.EntityContainerCannotExtendItself(this.Name));
                    }
                    else if (!Schema.SchemaManager.TryResolveType(null, _unresolvedExtendedEntityContainerName, out extendingEntityContainer))
                    { 
                        AddError(ErrorCode.InvalidEntityContainerNameInExtends, EdmSchemaErrorSeverity.Error,
                                System.Data.Entity.Strings.InvalidEntityContainerNameInExtends(_unresolvedExtendedEntityContainerName)); 
                    } 
                    else
                    { 
                        _entityContainerGettingExtended = (EntityContainer)extendingEntityContainer;

                        // Once you have successfully resolved the entity container, then you should call ResolveNames on the
                        // extending entity containers as well. This is because we will need to look up the chain for resolving 
                        // entity set names, since there might be association sets/ function imports that refer to entity sets
                        // belonging in extended entity containers 
                        _entityContainerGettingExtended.ResolveTopLevelNames(); 
                    }
                } 

                foreach (SchemaElement element in Members)
                {
                    element.ResolveTopLevelNames(); 
                }
 
                _isAlreadyResolved = true; 
            }
        } 

        internal override void ResolveSecondLevelNames()
        {
            base.ResolveSecondLevelNames(); 

            foreach (SchemaElement element in Members) 
            { 
                element.ResolveSecondLevelNames();
            } 
        }

        /// 
        /// Do all validation for this element here, and delegate to all sub elements 
        /// 
        internal override void Validate() 
        { 
            // Now before we clone all the entity sets from the entity container that this entity container is extending,
            // we need to make sure that the entity container that is getting extended is already validated. since it might 
            // be extending some other entity container, and we might want to populate this entity container, before
            // it gets extended
            if (!_isAlreadyValidated)
            { 
                base.Validate();
 
                // If this entity container extends some other entity container, then we should add all the 
                // sets and function imports from that entity container to this entity container
                if (this.ExtendingEntityContainer != null) 
                {
                    // Call Validate on the entity container that is getting extended, so that its entity set
                    // is populated
                    this.ExtendingEntityContainer.Validate(); 

                    foreach (SchemaElement element in this.ExtendingEntityContainer.Members) 
                    { 
                        AddErrorKind error = this.Members.TryAdd(element.Clone(this));
                        DuplicateOrEquivalentMemberNameWhileExtendingEntityContainer(element, error); 
                    }
                }

                HashSet tableKeys = new HashSet(); 

                foreach (SchemaElement element in Members) 
                { 
                    EntityContainerEntitySet entitySet = element as EntityContainerEntitySet;
                    if (entitySet != null && Schema.DataModel == SchemaDataModelOption.ProviderDataModel) 
                    {
                        CheckForDuplicateTableMapping(tableKeys, entitySet);
                    }
                    element.Validate(); 
                }
 
                ValidateRelationshipSetHaveUniqueEnds(); 

                ValidateOnlyBaseEntitySetTypeDefinesConcurrency(); 

                // Set isAlreadyValidated to true
                _isAlreadyValidated = true;
            } 
        }
 
        ///  
        /// Find the EntityContainerEntitySet in the same EntityContainer with the name from the extent
        /// attribute 
        /// 
        /// the name of the EntityContainerProperty to find
        /// The EntityContainerProperty it found or null if it fails to find it
        internal EntityContainerEntitySet FindEntitySet(string name) 
        {
            EntityContainer current = this; 
            while(current != null) 
            {
                foreach (EntityContainerEntitySet set in current.EntitySets) 
                {
                    if (Utils.CompareNames(set.Name, name) == 0)
                    {
                        return set; 
                    }
                } 
 
                current = current.ExtendingEntityContainer;
            } 

            return null;
        }
 
        private void DuplicateOrEquivalentMemberNameWhileExtendingEntityContainer(SchemaElement schemaElement,
            AddErrorKind error) 
        { 
            Debug.Assert(error != AddErrorKind.MissingNameError, "Since entity container members are already resolved, name must never be empty");
            Debug.Assert(this.ExtendingEntityContainer != null, "ExtendingEntityContainer must not be null"); 

            if (error != AddErrorKind.Succeeded)
            {
                Debug.Assert(error == AddErrorKind.DuplicateNameError, "Error must be duplicate name error"); 
                schemaElement.AddError(ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error,
                            System.Data.Entity.Strings.DuplicateMemberNameInExtendedEntityContainer( 
                                schemaElement.Name, ExtendingEntityContainer.Name, this.Name)); 
            }
        } 

        private void ValidateOnlyBaseEntitySetTypeDefinesConcurrency()
        {
            // collect all the base entitySet types 
            Dictionary baseEntitySetTypes = new Dictionary();
            foreach (SchemaElement element in Members) 
            { 
                EntityContainerEntitySet entitySet = element as EntityContainerEntitySet;
                if (entitySet != null && !baseEntitySetTypes.ContainsKey(entitySet.EntityType)) 
                {
                    baseEntitySetTypes.Add(entitySet.EntityType, entitySet);
                }
            } 

            // look through each type in this schema and see if it is derived from a base 
            // type if it is then see if it has some "new" Concurrency fields 
            foreach (SchemaType type in Schema.SchemaTypes)
            { 
                SchemaEntityType itemType = type as SchemaEntityType;
                if (itemType != null)
                {
                    EntityContainerEntitySet set; 
                    if (TypeIsSubTypeOf(itemType, baseEntitySetTypes, out set) &&
                       TypeDefinesNewConcurrencyProperties(itemType)) 
                    { 
                        AddError(ErrorCode.ConcurrencyRedefinedOnSubTypeOfEntitySetType,
                            EdmSchemaErrorSeverity.Error, 
                            System.Data.Entity.Strings.ConcurrencyRedefinedOnSubTypeOfEntitySetType(itemType.FQName, set.EntityType.FQName, set.FQName));
                    }
                }
            } 

        } 
 
        /// 
        /// Validates that if there are more than one relationship set referring to the same type, each role of the relationship type 
        /// never refers to the same entity set
        /// 
        private void ValidateRelationshipSetHaveUniqueEnds()
        { 
            // Contains the list of ends that have been visited and validated
            List alreadyValidatedEnds = new List(); 
            bool error = true; 

            foreach (EntityContainerRelationshipSet currentSet in this.RelationshipSets) 
            {
                foreach (EntityContainerRelationshipSetEnd currentSetEnd in currentSet.Ends)
                {
                    error = false; 
                    foreach (EntityContainerRelationshipSetEnd alreadyValidatedEnd in alreadyValidatedEnds)
                    { 
                        if (AreRelationshipEndsEqual(alreadyValidatedEnd, currentSetEnd)) 
                        {
                            AddError(ErrorCode.SimilarRelationshipEnd, 
                                     EdmSchemaErrorSeverity.Error,
                                     System.Data.Entity.Strings.SimilarRelationshipEnd(alreadyValidatedEnd.Name, alreadyValidatedEnd.ParentElement.FQName,
                                                         currentSetEnd.ParentElement.FQName, alreadyValidatedEnd.EntitySet.FQName, this.FQName));
                            error = true; 
                            break;
                        } 
                    } 
                    if (!error)
                    { 
                        alreadyValidatedEnds.Add(currentSetEnd);
                    }
                }
            } 
        }
 
        private static bool TypeIsSubTypeOf(SchemaEntityType itemType, Dictionary baseEntitySetTypes, out EntityContainerEntitySet set) 
        {
            if (itemType.IsTypeHierarchyRoot) 
            {
                // can't be a sub type if we are a base type
                set = null;
                return false; 
            }
 
            // walk up the hierarchy looking for a base that is the base type of an entityset 
            for (SchemaEntityType baseType = itemType.BaseType as SchemaEntityType; baseType != null; baseType = baseType.BaseType as SchemaEntityType)
            { 
                if (baseEntitySetTypes.ContainsKey(baseType))
                {
                    set = baseEntitySetTypes[baseType];
                    return true; 
                }
            } 
 
            set = null;
            return false; 
        }

        private static bool TypeDefinesNewConcurrencyProperties(SchemaEntityType itemType)
        { 
            foreach (StructuredProperty property in itemType.Properties)
            { 
                if (property.Type is ScalarType && MetadataHelper.GetConcurrencyMode(property.TypeUsage) != ConcurrencyMode.None) 
                {
                    return true; 
                }
            }

            return false; 
        }
 
        ///  
        /// Return the fully qualified name for entity container. Since EntityContainer no longer lives in a schema,
        /// the FQName should be same as that of the Name 
        /// 
        public override string FQName
        {
            get 
            {
                return this.Name; 
            } 
        }
 
        /// 
        ///
        /// 
        public override string Identity 
        {
            get 
            { 
                return Name;
            } 
        }

        /// 
        /// Adds a child EntitySet's tableKey (Schema/Table combination) to the validation collection 
        /// This is used to validate that no child EntitySets share a Schema.Table combination
        ///  
        private void CheckForDuplicateTableMapping(HashSet tableKeys, EntityContainerEntitySet entitySet) 
        {
            string schema; 
            string table;

            if (String.IsNullOrEmpty(entitySet.DbSchema))
            { 
                // if there is no specified DbSchema, use the parent EntityContainer's name
                schema = this.Name; 
            } 
            else
            { 
                schema = entitySet.DbSchema;
            }

 
            if (String.IsNullOrEmpty(entitySet.Table))
            { 
                // if there is no specified Table, use the EntitySet's name 
                table = entitySet.Name;
            } 
            else
            {
                table = entitySet.Table;
            } 

            // create a key using the DbSchema and Table 
            string tableKey = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}.{1}", schema, table); 
            if (entitySet.DefiningQuery != null)
            { 
                // don't consider the schema name for defining queries, because
                // we can't say for sure that it is the same as the entity container
                // so in this example
                // 
                // 
                //    
                //     Select col1 from dbi.ByVal 
                //   
                //    
                //   ...
                //
                // ByVal and ByVal1 should not conflict in our check
                tableKey = entitySet.Name; 
            }
 
            bool alreadyExisted = !tableKeys.Add(tableKey); 
            if (alreadyExisted)
            { 
                entitySet.AddError(ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.DuplicateEntitySetTable(entitySet.Name, schema, table));
            }
        }
 
        /// 
        /// Returns true if the given two ends are similar - the relationship type that this ends belongs to is the same 
        /// and the entity set refered by the ends are same and they have the same role name 
        /// 
        ///  
        /// 
        /// 
        private static bool AreRelationshipEndsEqual(EntityContainerRelationshipSetEnd left, EntityContainerRelationshipSetEnd right)
        { 
            Debug.Assert(left.ParentElement.ParentElement == right.ParentElement.ParentElement, "both end should belong to the same entity container");
 
            if (object.ReferenceEquals(left.EntitySet, right.EntitySet) && 
                object.ReferenceEquals(left.ParentElement.Relationship, right.ParentElement.Relationship) &&
                left.Name == right.Name) 
            {
                return true;
            }
 
            return false;
        } 
        #endregion 
    }
 
}

// 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