/// <summary>
        /// Validates the properties on an Entity.
        /// </summary>
        /// <param name="entity"></param>
        private void RemoveDuplicateConceptualEntityTypeKeysAndProperties(EntityType entity)
        {
            var processed = new List<string>();
            var propertiesToRemove = new List<EntityProperty>();
            foreach (var property in entity.Properties)
            {
                var isInvalidComplexType = property.IsComplexType(ConceptualSchema.Namespace) && !ConceptualSchema.ComplexTypes.Exists(property.Type.ToString(), ConceptualSchema.Namespace);
                if (isInvalidComplexType || processed.Contains(property.Name))
                    propertiesToRemove.Add(property);
                else
                    processed.Add(property.Name);
            }

            foreach (var e in propertiesToRemove)
            {
                entity.Properties.Remove(e);
            }

            entity.Properties = (from p in entity.Properties select p).ToList();

            if (entity.Key != null)
            {
                var keysProcessed = new List<string>();
                var keysToRemove = new List<PropertyRef>();
                foreach (PropertyRef property in entity.Key.PropertyRefs)
                {
                    if (!processed.Contains(property.Name) || keysProcessed.Contains(property.Name))
                        keysToRemove.Add(property);
                    else
                        keysProcessed.Add(property.Name);
                }

                foreach (var e in keysToRemove)
                {
                    entity.Key.PropertyRefs.Remove(e);
                }
            }
        }
        private void CreateConceptualNavigationProperty(EntityType entity, IAssociation association)
        {
            IEntity principalEntity;
            IEntity dependentEntity;
            bool isParentEntity;
            string key;
            string toRole;
            string fromRole;
            ResolveConceptualAssociationValues(association, out principalEntity, out dependentEntity, out isParentEntity, out key, out toRole, out fromRole);

            //11/4/2012 If an entity has an association to itself then we will modify the key if it's the child association.
            bool isSelfReferencingChild = !isParentEntity && principalEntity == dependentEntity;
            if (!isSelfReferencingChild && !association.IsParentManyToMany())
            {
                var temp = fromRole;
                fromRole = toRole;
                toRole = temp;
            }

            // 11/4/2012 Updated to check to see if a self referencing entity exists then we check the too and from roles. By checking only the to and from roles if it's a self referencing this allows custom names to be picked up.
            var navigationProperty = principalEntity == dependentEntity
                ? entity.NavigationProperties.FirstOrDefault(n => n.Relationship.Equals(String.Concat(ConceptualSchema.Namespace, ".", key)) && n.ToRole.Equals(toRole) && n.FromRole.Equals(fromRole))
                : entity.NavigationProperties.FirstOrDefault(n => n.Relationship.Equals(String.Concat(ConceptualSchema.Namespace, ".", key)));

            if (navigationProperty == null)
            {
                navigationProperty = new NavigationProperty() { Name = association.Name };
                entity.NavigationProperties.Add(navigationProperty);
            }

            if (String.IsNullOrEmpty(navigationProperty.Name) || association.Name.StartsWith(navigationProperty.Name))
                navigationProperty.Name = association.Name;

            navigationProperty.Relationship = String.Concat(ConceptualSchema.Namespace, ".", key);
            navigationProperty.FromRole = fromRole;
            navigationProperty.ToRole = toRole;
        }
        private void RemoveDuplicateConceptualComplexTypeProperties(IEntity entity, ComplexType type, EntityType entityType)
        {
            var processed = new List<string>();
            var propertiesToRemove = new List<ComplexTypeProperty>();
            foreach (var property in type.Properties)
            {
                if (processed.Contains(property.Name))
                    propertiesToRemove.Add(property);
                else
                    processed.Add(property.Name);
            }

            // Remove extra properties contained in the ComplexType that are not in the Entity.
            propertiesToRemove.AddRange(from property in type.Properties
                                        where
                                            !(from prop in entity.Properties select prop.KeyName).Contains(property.Name) &&
                                            _removedStorageEntityProperties.Contains(String.Format(PROPERTY_KEY, entity.EntityKeyName, property.Name).ToLower()) && // And it has been removed from the storage model.
                                            !propertiesToRemove.Contains(property)
                                        select property);

            if (entityType != null)
            {
                // Remove extra properties contained in the ComplexType that are not in the Entity.
                propertiesToRemove.AddRange(from property in type.Properties
                                            where !(from prop in entityType.Properties select entityType.Name).Contains(property.Name) && !propertiesToRemove.Contains(property)
                                            select property);
            }

            foreach (var e in propertiesToRemove)
            {
                type.Properties.Remove(e);
            }

            type.Properties = (from p in type.Properties select p).ToList();
        }
        private void CreateConceptualEntityTypeProperties(IEntity entity, EntityType entityType, bool isNewEntityType)
        {
            //<Property Name="CategoryId" Type="String" Nullable="false" MaxLength="10" Unicode="false" FixedLength="false" />
            foreach (ISchemaProperty property in entity.Properties)
            {
                var propertyName = ResolveEntityPropertyMappedName(entity.Name, property.KeyName, property.Name);
                var entityProperty = entityType.Properties.Where(p => propertyName.Equals(p.Name, StringComparison.OrdinalIgnoreCase) || property.KeyName.Equals(p.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                if (entityProperty == null)
                {
                    if (ExcludeProperty(property) || !isNewEntityType && !_newStorageEntityProperties.Contains(String.Format("{0}-{1}", entity.Name, property.Name)))
                        continue;

                    entityProperty = new EntityProperty() { Name = ResolveEntityPropertyMappedName(entity.Name, property.KeyName, property.Name) };
                    entityType.Properties.Add(entityProperty);
                }
                else if (ExcludeProperty(property))
                {
                    entityType.Properties.Remove(entityProperty);
                    continue;
                }

                entityProperty.Name = propertyName;

                //Note: If the SystemType is prefixed with System than it will throw an error saying it cannot be resolved.
                entityProperty.Type = GetSystemType(property);

                if (!property.IsNullable)
                    entityProperty.Nullable = property.IsNullable;

                if (String.IsNullOrEmpty(entityProperty.DefaultValue) && !String.IsNullOrEmpty(property.DefaultValue)) {
                    if (property.DefaultValue.ToLowerInvariant().Contains("autoincrement")) // Needed for sql anywhere
                        entityProperty.DefaultValue = null;
                    else if (String.Equals(property.BaseSystemType, "System.Boolean", StringComparison.OrdinalIgnoreCase))
                        entityProperty.DefaultValue = property.DefaultValue.ToLower();
                    else if (String.Equals(property.BaseSystemType, "System.Single", StringComparison.OrdinalIgnoreCase)
                        || String.Equals(property.BaseSystemType, "System.Int16", StringComparison.OrdinalIgnoreCase)
                        || String.Equals(property.BaseSystemType, "System.Int32", StringComparison.OrdinalIgnoreCase)
                        || String.Equals(property.BaseSystemType, "System.Int64", StringComparison.OrdinalIgnoreCase)
                        || String.Equals(property.BaseSystemType, "System.Byte", StringComparison.OrdinalIgnoreCase)
                        || String.Equals(property.BaseSystemType, "System.Decimal", StringComparison.OrdinalIgnoreCase)
                        || String.Equals(property.BaseSystemType, "System.Double", StringComparison.OrdinalIgnoreCase)
                        || String.Equals(property.BaseSystemType, "System.String", StringComparison.OrdinalIgnoreCase))
                        entityProperty.DefaultValue = property.DefaultValue;
                    else
                        entityProperty.DefaultValue = null;
                }
                else {
                    entityProperty.DefaultValue = null;
                }

                entityProperty.MaxLength = !String.IsNullOrEmpty(GetMaxLength(property)) ? GetMaxLength(property) : null;
                entityProperty.Precision = (property.DataType == DbType.Decimal || property.DataType == DbType.Currency && property.Precision > 0) ? property.Precision : (decimal?)null;
                entityProperty.Scale = (property.DataType == DbType.Decimal || property.DataType == DbType.Currency && property.Scale > 0) ? property.Scale : (decimal?)null;
                entityProperty.FixedLength = entityProperty.Type.Equals("String") || property.DataType == DbType.Binary ? property.FixedLength : (bool?)null;
                entityProperty.Unicode = entityProperty.Type.Equals("String") ? property.Unicode : (bool?)null;

                entityProperty.SetAttributeValue(EdmxConstants.IsIndexCustomAttribute, property.IsUnique ? Boolean.TrueString : null);

                if (property.IsIdentity || property.IsComputed)
                {
                    entityProperty.StoreGeneratedPattern = property.IsIdentity ? EdmxConstants.StoreGeneratedPatternIdentity : EdmxConstants.StoreGeneratedPatternComputed;
                    entityProperty.ConcurrencyMode = null;
                }
                else if (property.IsRowVersion)
                {
                    entityProperty.ConcurrencyMode = EdmxConstants.ConcurrencyModeFixed;
                    entityProperty.StoreGeneratedPattern = null;
                }
                else
                {
                    entityProperty.ConcurrencyMode = null;
                    entityProperty.StoreGeneratedPattern = null;
                }
            }
        }
        private void CreateConceptualEntityTypeKeys(IEntity entity, bool isNewView, EntityType entityType)
        {
            //<Key>
            //  <PropertyRef Name="CategoryId"  />
            //</Key>
            if (entity.HasKey || isNewView)
            {
                #region Remove extra key values.

                var items = from property in entityType.Key.PropertyRefs
                            where !(from prop in entity.Key.Properties select prop.Name).Contains(property.Name)
                            select property;

                // Remove all of the key properties that don't exist in the table entity.
                foreach (var property in items)
                {
                    entityType.Key.PropertyRefs.Remove(property);
                }

                #endregion

                foreach (var property in entity.Key.Properties.Where(p => entityType.Key.PropertyRefs.Count(pr => pr.Name == p.Name) == 0)) {
                    entityType.Key.PropertyRefs.Add(new PropertyRef() { Name =  ResolveEntityPropertyMappedName(entity.Name, property.KeyName, property.Name) });
                }
            }
            else if (entity is TableEntity)
            {
                entityType.Key.PropertyRefs.Clear();
            }
        }
        private EntityType CreateConceptualEntityType(IEntity entity, string entitySetName, string previousName, ref bool isNewView, out bool isNewEntityType)
        {
            //<EntityType Name="Category">
            var entityType = ConceptualSchema.EntityTypes.Where(e =>
                                                                previousName.Equals(e.Name, StringComparison.OrdinalIgnoreCase) ||
                                                                ResolveEntityMappedName(entity.EntityKey(), entity.Name).Equals(e.Name, StringComparison.OrdinalIgnoreCase) ||
                                                                entitySetName.Equals(e.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

            isNewEntityType = false;
            if (entityType == null)
            {
                entityType = new EntityType()
                {
                    Name = ResolveEntityMappedName(entity.EntityKey(), entity.Name),
                    Key = new EntityKeyElement()
                };

                ConceptualSchema.EntityTypes.Add(entityType);

                isNewView = entity is ViewEntity;
                isNewEntityType = true;
            }

            entityType.Name = ResolveEntityMappedName(entity.EntityKey(), entity.Name);
            entityType.SetAttributeValue(EdmxConstants.IsViewEntityCustomAttribute, entity is ViewEntity ? Boolean.TrueString : null);

            return entityType;
        }
        private void ValidateConceptualEntityComplexProperties(IEntity entity, EntityType entityType)
        {
            //<Property Name="ComplexProperty" Type="PetShopModel.Test" Nullable="false" />
            var invalidComplexTypeProperties = new List<EntityProperty>();
            foreach (var property in entityType.Properties.Where(p => p.IsComplexType(ConceptualSchema.Namespace)))
            {
                //<ComplexType Name="GetCategoryById_Result">
                var complexType = ConceptualSchema.ComplexTypes.Find(property.Type.ToString(), ConceptualSchema.Namespace);
                if (complexType == null)
                {
                    invalidComplexTypeProperties.Add(property);
                    continue;
                }

                RemoveDuplicateConceptualComplexTypeProperties(entity, complexType, entityType);

                if (!_conceptualComplexTypes.Contains(entity.Name))
                    _conceptualComplexTypes.Add(entity.Name);
            }

            foreach (var property in invalidComplexTypeProperties)
            {
                entityType.Properties.Remove(property);
            }
        }
        /// <summary>
        /// Validates an EntityType's Associations.
        /// </summary>
        /// <param name="entity"></param>
        private void ValidateConceptualEntityAssociations(EntityType entity)
        {
            var proccessed = new List<string>();
            var navigationsToRemove = new List<NavigationProperty>();
            foreach (var nav in entity.NavigationProperties)
            {
                //from navigationProperty in type.NavigationProperties
                //                       where !(from a in entity.Associations select String.Concat(ConceptualSchema.Namespace, ".", ResolveAssociationMappedName(a.AssociationKeyName))).Contains(navigationProperty.Relationship)
                //                       select navigationProperty;

                if (!proccessed.Contains(nav.Name) && ValidateConceptualNavigationProperty(nav))
                    proccessed.Add(nav.Name);
                else
                    navigationsToRemove.Add(nav);
            }

            foreach (var nav in navigationsToRemove)
            {
                entity.NavigationProperties.Remove(nav);
            }

            entity.NavigationProperties = (from n in entity.NavigationProperties select n).ToList();
        }