Skip to content
Browse files

Merge pull request #211 from tgmayfield/SubclassInterfaces

Subclass interfaces. Fixes NullReferenceExceptions caused by a null type.BaseType when the subclass type is an interface.
  • Loading branch information...
2 parents 4421b05 + d6dd56a commit 23f67a3209ba3cd43a59961f0ff0056aeb0d6627 @chester89 chester89 committed Mar 6, 2013
View
158 src/FluentNHibernate.Testing/PersistenceModelTests/SubclassPersistenceModelTests.cs
@@ -203,6 +203,46 @@ public void ShouldHandleEverettsWeirdMapping()
colorSource.Subclasses.ShouldContain(x => x.Type == typeof(Sauces.ReallyHotSauce));
colorSource.Subclasses.Count().ShouldEqual(2);
}
+
+ [Test]
+ public void CanBuildConfigurationForTablePerType()
+ {
+ var model = new PersistenceModel();
+ model.Add(new TablePerType.TPT_TopMap());
+ model.Add(new TablePerType.TPT_TopSubclassMap());
+ model.Add(new TablePerType.TPT_MiddleMap());
+ model.Add(new TablePerType.TPT_MiddleSubclassMap());
+
+ var classMapping = model.BuildMappings();
+ classMapping.Count().ShouldEqual(1);
+
+ var top = classMapping.First().Classes.First();
+ top.Subclasses.Count().ShouldEqual(2);
+
+ var middle = top.Subclasses.SingleOrDefault(sc => sc.Type == typeof(TablePerType.TPT_Middle));
+ middle.ShouldNotBeNull();
+ middle.Subclasses.Count().ShouldEqual(1);
+ }
+
+ [Test]
+ public void CanBuildConfigurationForTablePerTypeWithInterfaces()
+ {
+ var model = new PersistenceModel();
+ model.Add(new TablePerTypeWithInterfaces.TPTWI_ITopMap());
+ model.Add(new TablePerTypeWithInterfaces.TPTWI_TopSubclassMap());
+ model.Add(new TablePerTypeWithInterfaces.TPTWI_IMiddleMap());
+ model.Add(new TablePerTypeWithInterfaces.TPTWI_MiddleSubclassMap());
+
+ var classMapping = model.BuildMappings();
+ classMapping.Count().ShouldEqual(1);
+
+ var top = classMapping.First().Classes.First();
+ top.Subclasses.Count().ShouldEqual(2);
+
+ var middle = top.Subclasses.SingleOrDefault(sc => sc.Type == typeof(TablePerTypeWithInterfaces.TPTWI_IMiddle));
+ middle.ShouldNotBeNull();
+ middle.Subclasses.Count().ShouldEqual(1);
+ }
}
namespace Thoughts
@@ -365,6 +405,124 @@ public class I_BottomMostMap : SubclassMap<I_BottomMost>
{ }
}
+ namespace TablePerType
+ {
+ public class TPT_Top
+ {
+ public virtual int Id { get; protected set; }
+ }
+ public class TPT_Middle
+ : TPT_Top
+ {
+ public virtual string MiddleProperty { get; set; }
+ }
+ public class TPT_TopSubclass
+ : TPT_Top
+ {
+ }
+ public class TPT_MiddleSubclass
+ : TPT_Middle
+ {
+ public virtual string OwnProperty { get; set; }
+ }
+
+ public class TPT_TopMap
+ : ClassMap<TPT_Top>
+ {
+ public TPT_TopMap()
+ {
+ Id(x => x.Id);
+ }
+ }
+ public class TPT_TopSubclassMap
+ : SubclassMap<TPT_TopSubclass>
+ {
+ public TPT_TopSubclassMap()
+ {
+ KeyColumn("Id");
+ }
+ }
+ public class TPT_MiddleMap
+ : SubclassMap<TPT_Middle>
+ {
+ public TPT_MiddleMap()
+ {
+ KeyColumn("Id");
+ Map(x => x.MiddleProperty);
+ }
+ }
+ public class TPT_MiddleSubclassMap
+ : SubclassMap<TPT_MiddleSubclass>
+ {
+ public TPT_MiddleSubclassMap()
+ {
+ KeyColumn("Id");
+ Map(x => x.OwnProperty);
+ }
+ }
+ }
+
+ namespace TablePerTypeWithInterfaces
+ {
+ public interface TPTWI_ITop
+ {
+ int Id { get; }
+ }
+ public interface TPTWI_IMiddle
+ : TPTWI_ITop
+ {
+ string MiddleProperty { get; set; }
+ }
+
+ public class TPTWI_TopSubclass
+ : TPTWI_ITop
+ {
+ public virtual int Id { get; protected set; }
+ }
+ public class TPTWI_MiddleSubclass
+ : TPTWI_TopSubclass, TPTWI_IMiddle
+ {
+ public virtual string MiddleProperty { get; set; }
+ public virtual string OwnProperty { get; set; }
+ }
+
+ public class TPTWI_ITopMap
+ : ClassMap<TPTWI_ITop>
+ {
+ public TPTWI_ITopMap()
+ {
+ Id(x => x.Id);
+ }
+ }
+ public class TPTWI_TopSubclassMap
+ : SubclassMap<TPTWI_TopSubclass>
+ {
+ public TPTWI_TopSubclassMap()
+ {
+ Extends<TPTWI_ITop>();
+ KeyColumn("Id");
+ }
+ }
+ public class TPTWI_IMiddleMap
+ : SubclassMap<TPTWI_IMiddle>
+ {
+ public TPTWI_IMiddleMap()
+ {
+ KeyColumn("Id");
+ Map(x => x.MiddleProperty);
+ }
+ }
+ public class TPTWI_MiddleSubclassMap
+ : SubclassMap<TPTWI_MiddleSubclass>
+ {
+ public TPTWI_MiddleSubclassMap()
+ {
+ KeyColumn("Id");
+ Map(x => x.OwnProperty);
+ }
+ }
+ }
+
namespace Branching
{
public class B_Top
View
11 src/FluentNHibernate/Mapping/SubclassMap.cs
@@ -292,11 +292,16 @@ SubclassMapping IIndeterminateSubclassMappingProvider.GetSubclassMapping(Subclas
attributes.Set("DiscriminatorValue", Layer.Defaults, typeof(T).Name);
// TODO: un-hardcode this
- var key = new KeyMapping();
- key.AddColumn(Layer.Defaults, new ColumnMapping(typeof(T).BaseType.Name + "_id"));
+ Type baseType = typeof(T).BaseType
+ ?? attributes.Get("Extends") as Type;
+ if (baseType != null)
+ {
+ var key = new KeyMapping();
+ key.AddColumn(Layer.Defaults, new ColumnMapping(baseType.Name + "_id"));
+ attributes.Set("Key", Layer.Defaults, key);
+ }
attributes.Set("TableName", Layer.Defaults, GetDefaultTableName());
- attributes.Set("Key", Layer.Defaults, key);
// TODO: this is nasty, we should find a better way
mapping.OverrideAttributes(attributes.Clone());
View
2 src/FluentNHibernate/Visitors/SeparateSubclassVisitor.cs
@@ -91,7 +91,7 @@ private bool IsMapped(Type type, IEnumerable<IIndeterminateSubclassMappingProvid
var subclassType = subclassProvider.EntityType;
var level = 0;
- bool implOfParent = parentType.IsInterface
+ bool implOfParent = (parentType.IsInterface || subclassType.IsInterface)
? DistanceFromParentInterface(parentType, subclassType, ref level)
: DistanceFromParentBase(parentType, subclassType.BaseType, ref level);

0 comments on commit 23f67a3

Please sign in to comment.
Something went wrong with that request. Please try again.