Skip to content

Commit d147b77

Browse files
committed
Fix mapping of intermediate inherited classes
When determining a parent entity for a mapped class in hierarchy consider only mapped classes. Fixes #1358
1 parent 8477eeb commit d147b77

File tree

1 file changed

+48
-34
lines changed

1 file changed

+48
-34
lines changed

src/NHibernate/Mapping/ByCode/ModelMapper.cs

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -549,29 +549,32 @@ public HbmMapping CompileMappingFor(IEnumerable<System.Type> types)
549549
throw new ArgumentNullException("types");
550550
}
551551

552-
var typeToMap = OrderTypesByHierarchy(types);
552+
var entitiesToMap = GetEntitiesToMapOrderedByHierarchy(types);
553553

554554
string defaultAssemblyName = null;
555555
string defaultNamespace = null;
556-
System.Type firstType = typeToMap.FirstOrDefault();
557-
if (firstType != null && typeToMap.All(t => t.Assembly.Equals(firstType.Assembly)))
556+
System.Type firstType = entitiesToMap.FirstOrDefault();
557+
if (firstType != null && entitiesToMap.All(t => t.Assembly.Equals(firstType.Assembly)))
558558
{
559559
//NH-2831: always use the full name of the assembly because it may come from GAC
560560
defaultAssemblyName = firstType.Assembly.GetName().FullName;
561561
}
562-
if (firstType != null && typeToMap.All(t => t.Namespace == firstType.Namespace))
562+
if (firstType != null && entitiesToMap.All(t => t.Namespace == firstType.Namespace))
563563
{
564564
defaultNamespace = firstType.Namespace;
565565
}
566566
var mapping = NewHbmMapping(defaultAssemblyName, defaultNamespace);
567-
foreach (var type in RootClasses(typeToMap))
567+
foreach (var type in RootClasses(entitiesToMap))
568568
{
569569
MapRootClass(type, mapping);
570570
}
571-
foreach (var type in Subclasses(typeToMap))
571+
572+
var entitiesSet = new HashSet<System.Type>(entitiesToMap);
573+
foreach (var type in Subclasses(entitiesToMap))
572574
{
573-
AddSubclassMapping(mapping, type);
575+
AddSubclassMapping(mapping, type, entitiesSet);
574576
}
577+
575578
return mapping;
576579
}
577580

@@ -581,21 +584,27 @@ public IEnumerable<HbmMapping> CompileMappingForEach(IEnumerable<System.Type> ty
581584
{
582585
throw new ArgumentNullException("types");
583586
}
584-
var typeToMap = OrderTypesByHierarchy(types);
587+
588+
var entitiesToMap = GetEntitiesToMapOrderedByHierarchy(types);
585589

586590
//NH-2831: always use the full name of the assembly because it may come from GAC
587-
foreach (var type in RootClasses(typeToMap))
591+
var mappings = new List<HbmMapping>();
592+
foreach (var type in RootClasses(entitiesToMap))
588593
{
589594
var mapping = NewHbmMapping(type.Assembly.GetName().FullName, type.Namespace);
590595
MapRootClass(type, mapping);
591-
yield return mapping;
596+
mappings.Add(mapping);
592597
}
593-
foreach (var type in Subclasses(typeToMap))
598+
599+
var entitiesSet = new HashSet<System.Type>(entitiesToMap);
600+
foreach (var type in Subclasses(entitiesToMap))
594601
{
595602
var mapping = NewHbmMapping(type.Assembly.GetName().FullName, type.Namespace);
596-
AddSubclassMapping(mapping, type);
597-
yield return mapping;
603+
AddSubclassMapping(mapping, type, entitiesSet);
604+
mappings.Add(mapping);
598605
}
606+
607+
return mappings;
599608
}
600609

601610
private HbmMapping NewHbmMapping(string defaultAssemblyName, string defaultNamespace)
@@ -608,40 +617,40 @@ private HbmMapping NewHbmMapping(string defaultAssemblyName, string defaultNames
608617
return hbmMapping;
609618
}
610619

611-
private IEnumerable<System.Type> Subclasses(IEnumerable<System.Type> types)
620+
private IEnumerable<System.Type> Subclasses(IEnumerable<System.Type> entities)
612621
{
613-
return types.Where(type => modelInspector.IsEntity(type) && !modelInspector.IsRootEntity(type));
622+
return entities.Where(type => !modelInspector.IsRootEntity(type));
614623
}
615624

616-
private IEnumerable<System.Type> RootClasses(IEnumerable<System.Type> types)
625+
private IEnumerable<System.Type> RootClasses(IEnumerable<System.Type> entities)
617626
{
618-
return types.Where(type => modelInspector.IsEntity(type) && modelInspector.IsRootEntity(type));
627+
return entities.Where(type => modelInspector.IsRootEntity(type));
619628
}
620629

621-
private void AddSubclassMapping(HbmMapping mapping, System.Type type)
630+
private void AddSubclassMapping(HbmMapping mapping, System.Type type, ICollection<System.Type> mappedEntities)
622631
{
623632
if (modelInspector.IsTablePerClassHierarchy(type))
624633
{
625-
MapSubclass(type, mapping);
634+
MapSubclass(type, mapping, mappedEntities);
626635
}
627636
else if (modelInspector.IsTablePerClass(type))
628637
{
629-
MapJoinedSubclass(type, mapping);
638+
MapJoinedSubclass(type, mapping, mappedEntities);
630639
}
631640
else if (modelInspector.IsTablePerConcreteClass(type))
632641
{
633-
MapUnionSubclass(type, mapping);
642+
MapUnionSubclass(type, mapping, mappedEntities);
634643
}
635644
}
636645

637-
private void MapUnionSubclass(System.Type type, HbmMapping mapping)
646+
private void MapUnionSubclass(System.Type type, HbmMapping mapping, ICollection<System.Type> mappedEntities)
638647
{
639648
var classMapper = new UnionSubclassMapper(type, mapping);
640649

641650
IEnumerable<MemberInfo> candidateProperties = null;
642-
if (!modelInspector.IsEntity(type.BaseType))
651+
if (!mappedEntities.Contains(type.BaseType))
643652
{
644-
System.Type baseType = GetEntityBaseType(type);
653+
var baseType = GetEntityBaseType(type, mappedEntities);
645654
if (baseType != null)
646655
{
647656
classMapper.Extends(baseType);
@@ -659,13 +668,13 @@ private void MapUnionSubclass(System.Type type, HbmMapping mapping)
659668
MapProperties(type, propertiesToMap, classMapper);
660669
}
661670

662-
private void MapSubclass(System.Type type, HbmMapping mapping)
671+
private void MapSubclass(System.Type type, HbmMapping mapping, ICollection<System.Type> mappedEntities)
663672
{
664673
var classMapper = new SubclassMapper(type, mapping);
665674
IEnumerable<MemberInfo> candidateProperties = null;
666-
if (!modelInspector.IsEntity(type.BaseType))
675+
if (!mappedEntities.Contains(type.BaseType))
667676
{
668-
System.Type baseType = GetEntityBaseType(type);
677+
var baseType = GetEntityBaseType(type, mappedEntities);
669678
if (baseType != null)
670679
{
671680
classMapper.Extends(baseType);
@@ -701,20 +710,21 @@ private void MapSubclass(System.Type type, HbmMapping mapping)
701710
InvokeAfterMapSubclass(type, classMapper);
702711
}
703712

704-
private void MapJoinedSubclass(System.Type type, HbmMapping mapping)
713+
private void MapJoinedSubclass(System.Type type, HbmMapping mapping, ICollection<System.Type> mappedEntities)
705714
{
706715
var classMapper = new JoinedSubclassMapper(type, mapping);
707716
IEnumerable<MemberInfo> candidateProperties = null;
708-
if (!modelInspector.IsEntity(type.BaseType))
717+
if (!mappedEntities.Contains(type.BaseType))
709718
{
710-
System.Type baseType = GetEntityBaseType(type);
719+
var baseType = GetEntityBaseType(type, mappedEntities);
711720
if (baseType != null)
712721
{
713722
classMapper.Extends(baseType);
714723
classMapper.Key(km => km.Column(baseType.Name.ToLowerInvariant() + "_key"));
715724
candidateProperties = membersProvider.GetSubEntityMembers(type, baseType);
716725
}
717726
}
727+
718728
candidateProperties = candidateProperties ?? membersProvider.GetSubEntityMembers(type, type.BaseType);
719729
IEnumerable<MemberInfo> propertiesToMap =
720730
candidateProperties.Where(p => modelInspector.IsPersistentProperty(p) && !modelInspector.IsPersistentId(p));
@@ -726,18 +736,19 @@ private void MapJoinedSubclass(System.Type type, HbmMapping mapping)
726736
MapProperties(type, propertiesToMap, classMapper);
727737
}
728738

729-
private System.Type GetEntityBaseType(System.Type type)
739+
private static System.Type GetEntityBaseType(System.Type type, ICollection<System.Type> mappedEntities)
730740
{
731741
System.Type analyzingType = type;
732742
while (analyzingType != null && analyzingType != typeof (object))
733743
{
734744
analyzingType = analyzingType.BaseType;
735-
if (modelInspector.IsEntity(analyzingType))
745+
if (mappedEntities.Contains(analyzingType))
736746
{
737747
return analyzingType;
738748
}
739749
}
740-
return type.GetInterfaces().FirstOrDefault(i => modelInspector.IsEntity(i));
750+
751+
return type.GetInterfaces().FirstOrDefault(i => mappedEntities.Contains(i));
741752
}
742753

743754
private void MapRootClass(System.Type type, HbmMapping mapping)
@@ -1805,7 +1816,7 @@ public IEnumerable<HbmMapping> CompileMappingForEachExplicitlyAddedEntity()
18051816
return CompileMappingForEach(customizerHolder.GetAllCustomizedEntities());
18061817
}
18071818

1808-
private static List<System.Type> OrderTypesByHierarchy(IEnumerable<System.Type> types)
1819+
private List<System.Type> GetEntitiesToMapOrderedByHierarchy(IEnumerable<System.Type> types)
18091820
{
18101821
var typesCache = new HashSet<System.Type>(types);
18111822

@@ -1815,6 +1826,9 @@ public IEnumerable<HbmMapping> CompileMappingForEachExplicitlyAddedEntity()
18151826
var type = typesCache.First();
18161827
result.AddRange(type.GetHierarchyFromBase().Where(baseType => typesCache.Remove(baseType)));
18171828
}
1829+
1830+
result.RemoveAll(type => !modelInspector.IsEntity(type));
1831+
18181832
return result;
18191833
}
18201834
}

0 commit comments

Comments
 (0)