private IEnumerable <IContentTypeComposition> GetAllTypesInternal()
        {
            var contentTypes = new Dictionary <int, IContentTypeComposition>();

            // get content types
            var sql1 = Sql()
                       .Select <ContentTypeDto>(r => r.Select(x => x.NodeDto))
                       .From <ContentTypeDto>()
                       .InnerJoin <NodeDto>().On <ContentTypeDto, NodeDto>((ct, n) => ct.NodeId == n.NodeId)
                       .OrderBy <ContentTypeDto>(x => x.NodeId);

            var contentTypeDtos = Database.Fetch <ContentTypeDto>(sql1);

            // get allowed content types
            var sql2 = Sql()
                       .Select <ContentTypeAllowedContentTypeDto>()
                       .From <ContentTypeAllowedContentTypeDto>()
                       .OrderBy <ContentTypeAllowedContentTypeDto>(x => x.Id);

            var allowedDtos = Database.Fetch <ContentTypeAllowedContentTypeDto>(sql2);

            // prepare
            // note: same alias could be used for media, content... but always different ids = ok
            var aliases = contentTypeDtos.ToDictionary(x => x.NodeId, x => x.Alias);

            // create
            var allowedDtoIx = 0;

            foreach (var contentTypeDto in contentTypeDtos)
            {
                // create content type
                IContentTypeComposition contentType;
                if (contentTypeDto.NodeDto.NodeObjectType == Constants.ObjectTypes.MediaType)
                {
                    contentType = ContentTypeFactory.BuildMediaTypeEntity(contentTypeDto);
                }
                else if (contentTypeDto.NodeDto.NodeObjectType == Constants.ObjectTypes.DocumentType)
                {
                    contentType = ContentTypeFactory.BuildContentTypeEntity(contentTypeDto);
                }
                else if (contentTypeDto.NodeDto.NodeObjectType == Constants.ObjectTypes.MemberType)
                {
                    contentType = ContentTypeFactory.BuildMemberTypeEntity(contentTypeDto);
                }
                else
                {
                    throw new PanicException($"The node object type {contentTypeDto.NodeDto.NodeObjectType} is not supported");
                }
                contentTypes.Add(contentType.Id, contentType);

                // map allowed content types
                var allowedContentTypes = new List <ContentTypeSort>();
                while (allowedDtoIx < allowedDtos.Count && allowedDtos[allowedDtoIx].Id == contentTypeDto.NodeId)
                {
                    var allowedDto = allowedDtos[allowedDtoIx];
                    if (!aliases.TryGetValue(allowedDto.AllowedId, out var alias))
                    {
                        continue;
                    }
                    allowedContentTypes.Add(new ContentTypeSort(new Lazy <int>(() => allowedDto.AllowedId), allowedDto.SortOrder, alias));
                    allowedDtoIx++;
                }
                contentType.AllowedContentTypes = allowedContentTypes;
            }

            MapTemplates(contentTypes);
            MapComposition(contentTypes);
            MapGroupsAndProperties(contentTypes);

            // finalize
            foreach (var contentType in contentTypes.Values)
            {
                contentType.ResetDirtyProperties(false);
            }

            return(contentTypes.Values);
        }