private static EntityType GetOrCreateEntityType(
            Type type,
            ModelConfiguration modelConfiguration,
            BreezeMetadata metadata)
        {
            if (metadata.StructuralTypes.FirstOrDefault(o => o.Type == type) is EntityType entityType)
            {
                return(entityType);
            }

            entityType = new EntityType(type)
            {
                DefaultResourceName  = modelConfiguration.ResourceName,
                AutoGeneratedKeyType = AutoGeneratedKeyType.KeyGenerator,
                Custom = modelConfiguration.Custom
            };

            if (entityType.DefaultResourceName != null)
            {
                metadata.ResourceEntityTypeMap.Add(modelConfiguration.ResourceName, GetBreezeTypeFullName(type));
            }

            metadata.StructuralTypes.Add(entityType);

            return(entityType);
        }
        private void AddSyntheticForeignKeyProperties(
            ModelMetadata modelMetadata,
            EntityType entityType,
            ModelConfiguration modelConfiguration)
        {
            foreach (var syntheticProperty in modelMetadata.SyntheticForeignKeyProperties.Values.Where(o => !o.Derived))
            {
                var memberConfiguration      = modelConfiguration.GetSyntheticMember(syntheticProperty.Name);
                var associationConfiguration = modelConfiguration.GetMember(syntheticProperty.AssociationPropertyName);
                if (memberConfiguration?.Ignored == true || associationConfiguration?.Ignored == true && memberConfiguration?.Ignored == null)
                {
                    continue;
                }

                var dataProperty = CreateDataProperty(
                    syntheticProperty.Name,
                    syntheticProperty.IdentifierDataType,
                    syntheticProperty.IsPartOfKey,
                    associationConfiguration?.IsNullable ?? syntheticProperty.IsNullable,
                    false,
                    memberConfiguration,
                    entityType,
                    associationConfiguration?.MaxLength ?? syntheticProperty.IdentifierLength);

                dataProperty.IsUnmapped = true;
                entityType.DataProperties.Add(dataProperty);
            }
        }
        private void AddAssociationProperties(
            string[] propertyNames,
            IType[] propertyTypes,
            bool partsOfKey,
            Func <int, CascadeStyle> getCascadeStyle,
            EntityType entityType,
            IReadOnlyCollection <string> superProperties,
            ModelConfiguration modelConfiguration,
            EntityMetadata entityMetadata)
        {
            for (var i = 0; i < propertyNames.Length; i++)
            {
                var propertyType        = propertyTypes[i] as IAssociationType;
                var propertyName        = propertyNames[i];
                var memberConfiguration = modelConfiguration.GetMember(propertyNames[i]);
                if (memberConfiguration?.Ignored == true ||
                    superProperties?.Contains(propertyName) == true ||
                    propertyType == null)
                {
                    continue;
                }

                var navigationProperty = CreateNavigationProperty(propertyType, propertyName, i, partsOfKey, getCascadeStyle, entityType, entityMetadata);
                if (navigationProperty != null)
                {
                    entityType.NavigationProperties.Add(navigationProperty);
                }
            }
        }
        private void AddIncludedMembers(
            EntityType entityType,
            ModelConfiguration modelConfiguration,
            ModelMetadata metadata)
        {
            foreach (var memberConfiguration in modelConfiguration.Members.Values)
            {
                if (
                    memberConfiguration.Ignored != false ||
                    metadata.AllProperties.Contains(memberConfiguration.MemberName))
                {
                    continue;
                }

                var dataProperty = CreateDataProperty(
                    memberConfiguration.MemberName,
                    _dataTypeProvider.GetDataType(memberConfiguration.MemberType),
                    false,
                    IsNullable(memberConfiguration.MemberType),
                    false,
                    memberConfiguration,
                    entityType,
                    null);

                dataProperty.IsUnmapped = true;
                entityType.DataProperties.Add(dataProperty);
            }
        }
        private void AddProperties(
            EntityMetadata entityMetadata,
            EntityType entityType,
            ModelConfiguration modelConfiguration,
            BreezeMetadata metadata)
        {
            var persister = entityMetadata.EntityPersister;

            AddDataProperties(
                persister.PropertyNames,
                persister.PropertyTypes,
                persister.PropertyNullability,
                entityMetadata.DerivedPropertyNames,
                persister.VersionProperty,
                false,
                entityType,
                modelConfiguration,
                metadata,
                persister.Factory);
            AddIdentifierProperties(persister, entityType, modelConfiguration, entityMetadata, metadata);
            AddSyntheticMembers(entityType, modelConfiguration);
            AddSyntheticForeignKeyProperties(entityMetadata, entityType, modelConfiguration);
            AddIncludedMembers(entityType, modelConfiguration, entityMetadata);

            // We do the association properties after the data properties, so we can do the foreign key lookups
            AddAssociationProperties(
                persister.PropertyNames,
                persister.PropertyTypes,
                false,
                i => persister.PropertyCascadeStyles[i],
                entityType,
                entityMetadata.DerivedPropertyNames,
                modelConfiguration,
                entityMetadata);
        }
        private void AddIdentifierProperties(
            AbstractEntityPersister persister,
            EntityType entityType,
            ModelConfiguration modelConfiguration,
            EntityMetadata entityMetadata,
            BreezeMetadata metadata)
        {
            // Add the identifier properties only for the root class
            if (persister.IsInherited)
            {
                return;
            }

            if (persister.HasIdentifierProperty)
            {
                var memberConfiguration = modelConfiguration.GetMember(persister.IdentifierPropertyName);
                var dataProperty        = CreateDataProperty(
                    persister.IdentifierPropertyName,
                    persister.IdentifierType,
                    true,
                    false,
                    false,
                    memberConfiguration,
                    entityType,
                    persister.Factory);
                entityType.DataProperties.Insert(0, dataProperty);
            }
            else if (persister.IdentifierType is IAbstractComponentType componentType)
            {
                modelConfiguration = _breezeConfigurator.GetModelConfiguration(componentType.ReturnedClass);
                AddDataProperties(
                    componentType.PropertyNames,
                    componentType.Subtypes,
                    componentType.PropertyNullability,
                    null,
                    null,
                    true,
                    entityType,
                    modelConfiguration,
                    metadata,
                    persister.Factory);
                AddAssociationProperties(
                    componentType.PropertyNames,
                    componentType.Subtypes,
                    true,
                    i => componentType.GetCascadeStyle(i),
                    entityType,
                    null,
                    modelConfiguration,
                    entityMetadata);
            }
        }
        private void AddSyntheticMembers(
            EntityType entityType,
            ModelConfiguration modelConfiguration)
        {
            foreach (var memberConfiguration in modelConfiguration.SyntheticMembers.Values.Where(o => o.Added))
            {
                var dataProperty = CreateDataProperty(
                    memberConfiguration.MemberName,
                    _dataTypeProvider.GetDataType(memberConfiguration.MemberType),
                    false,
                    IsNullable(memberConfiguration.MemberType),
                    false,
                    memberConfiguration,
                    entityType,
                    null);

                dataProperty.IsUnmapped = true;
                entityType.DataProperties.Add(dataProperty);
            }
        }
        private void AddEntityType(
            EntityMetadata entityMetadata,
            BreezeMetadata metadata)
        {
            var type = entityMetadata.Type;
            var modelConfiguration = _breezeConfigurator.GetModelConfiguration(type);
            var entityType         = new EntityType(type)
            {
                BaseTypeName = entityMetadata.BaseType != null
                    ? GetBreezeTypeFullName(entityMetadata.BaseType)
                    : null,
                AutoGeneratedKeyType = modelConfiguration.AutoGeneratedKeyType ?? entityMetadata.AutoGeneratedKeyType,
                DefaultResourceName  = modelConfiguration.ResourceName ?? Pluralize(type.Name),
                Custom = modelConfiguration.Custom
            };

            metadata.ResourceEntityTypeMap.Add(entityType.DefaultResourceName, GetBreezeTypeFullName(type));

            AddProperties(entityMetadata, entityType, modelConfiguration, metadata);

            metadata.StructuralTypes.Add(entityType);
        }