/// <inheritdoc/>
        protected override IPathNode VisitDomainModel(DomainModel domainModel)
        {
            // Build tables, columns and primary indexes
            foreach (var primaryIndex in domainModel.RealIndexes.Where(i => i.IsPrimary))
            {
                Visit(primaryIndex);
            }

            // Build full-text indexes
            foreach (var fullTextIndex in domainModel.FullTextIndexes)
            {
                Visit(fullTextIndex);
            }

            // Build foreign keys
            var buildForeignKeys = BuildForeignKeys &&
                                   providerInfo.Supports(ProviderFeatures.ForeignKeyConstraints);

            if (buildForeignKeys)
            {
                foreach (var group in domainModel.Associations.Where(a => a.Ancestors.Count == 0))
                {
                    Visit(group);
                }
            }

            // Build keys and sequences
            foreach (KeyInfo keyInfo in domainModel.Hierarchies.Select(h => h.Key))
            {
                Visit(keyInfo);
            }

            var buildHierarchyForeignKeys = BuildHierarchyForeignKeys &&
                                            providerInfo.Supports(ProviderFeatures.ForeignKeyConstraints);

            if (!buildHierarchyForeignKeys)
            {
                return(targetModel);
            }

            // Build hierarchy foreign keys
            var indexPairs = new Dictionary <Pair <IndexInfo>, object>();

            foreach (var type in domainModel.Types.Entities)
            {
                if (type.Hierarchy == null || type.Hierarchy.InheritanceSchema == InheritanceSchema.ConcreteTable)
                {
                    continue;
                }
                if (type.Indexes.PrimaryIndex.IsVirtual)
                {
                    Dictionary <TypeInfo, int> typeOrder = type.GetAncestors()
                                                           .AddOne(type)
                                                           .Select((t, i) => new { Type = t, Index = i })
                                                           .ToDictionary(a => a.Type, a => a.Index);
                    List <IndexInfo> realPrimaryIndexes = type.Indexes.RealPrimaryIndexes
                                                          .OrderBy(index => typeOrder[index.ReflectedType])
                                                          .ToList();
                    for (int i = 0; i < realPrimaryIndexes.Count - 1; i++)
                    {
                        if (realPrimaryIndexes[i] != realPrimaryIndexes[i + 1])
                        {
                            var pair = new Pair <IndexInfo>(realPrimaryIndexes[i], realPrimaryIndexes[i + 1]);
                            indexPairs[pair] = null;
                        }
                    }
                }
            }
            foreach (var indexPair in indexPairs.Keys)
            {
                var referencedIndex         = indexPair.First;
                var referencingIndex        = indexPair.Second;
                var referencingTable        = targetModel.Tables[resolver.GetNodeName(referencingIndex.ReflectedType)];
                var referencedTable         = targetModel.Tables[resolver.GetNodeName(referencedIndex.ReflectedType)];
                var storageReferencingIndex = FindIndex(
                    referencingTable, referencingIndex.KeyColumns.Select(ci => ci.Key.Name).ToList());

                string foreignKeyName = nameBuilder.BuildHierarchyForeignKeyName(referencingIndex.ReflectedType, referencedIndex.ReflectedType);
                CreateHierarchyForeignKey(referencingTable, referencedTable, storageReferencingIndex, foreignKeyName);
            }

            return(targetModel);
        }