From 261594c1d2b70eb909ddf349dc249e7167f9b7b2 Mon Sep 17 00:00:00 2001 From: Radim-Kohler Date: Mon, 27 Oct 2014 14:01:06 +0100 Subject: [PATCH 1/2] NH-3198, Proposal how to fix - Have Mapping By Code Support Dynamic Component Inside Join --- .../JoinDynamicComponentTests.cs | 106 ++++++++++++++++++ src/NHibernate.Test/NHibernate.Test.csproj | 1 + src/NHibernate/Mapping/ByCode/IJoinMapper.cs | 2 +- .../Impl/CustomizersImpl/JoinCustomizer.cs | 8 ++ src/NHibernate/Mapping/ByCode/ModelMapper.cs | 4 + 5 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 src/NHibernate.Test/MappingByCode/ExplicitMappingTests/JoinDynamicComponentTests.cs diff --git a/src/NHibernate.Test/MappingByCode/ExplicitMappingTests/JoinDynamicComponentTests.cs b/src/NHibernate.Test/MappingByCode/ExplicitMappingTests/JoinDynamicComponentTests.cs new file mode 100644 index 00000000000..f1a3c4c6c78 --- /dev/null +++ b/src/NHibernate.Test/MappingByCode/ExplicitMappingTests/JoinDynamicComponentTests.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections; +using NHibernate.Cfg.MappingSchema; +using NHibernate.Mapping.ByCode; +using NHibernate.Mapping.ByCode.Conformist; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.MappingByCode.ExplicitMappingTests +{ + public class JoinDynamicComponentTests + { + public class MyClass + { + public virtual int Code { get; set; } + public virtual string Name { get; set; } + public virtual MyOther Relation { get; set; } + public virtual MyOther JoinedRelation { get; set; } + public virtual IDictionary Attributes { get; set; } + public virtual IDictionary JoinedAttributes { get; set; } + } + + public class MyOther + { + public int Id { get; set; } + } + + public class MyClassMap : ClassMapping + { + public MyClassMap() + { + + this.Component(p => p.Attributes, + new + { + IsVisible = false, + Hash = default(Guid), + Reference = default(MyOther) + }, + m => + { + m.Property(p => p.IsVisible); + m.Property(p => p.Hash); + m.ManyToOne(p => p.Reference); + }); + + Property(x => x.Code); + Join("JoinedAttributes", x => + { + x.Property(p => p.Name); + x.Component(p => p.JoinedAttributes, + new + { + OtherReference = default(MyOther), + Description = string.Empty, + Age = 0, + }, + m => + { + m.ManyToOne(p => p.OtherReference); + m.Property(p => p.Description); + m.Property(p => p.Age); + }); + x.ManyToOne(p => p.JoinedRelation); + }); + + ManyToOne(x => x.Relation); + } + } + + [Test] + public void JoinedDynamicComponentShouldBeNestedInJoin() + { + var mapper = new ModelMapper(); + mapper.AddMapping(typeof(MyClassMap)); + var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities(); + + var mappingXml = mapping.AsString(); + Assert.AreEqual(mappingXml, +@" + + + + + + + + + + + + + + + + + + + + + +"); + } + + } +} \ No newline at end of file diff --git a/src/NHibernate.Test/NHibernate.Test.csproj b/src/NHibernate.Test/NHibernate.Test.csproj index 2533d1bd023..c5c9a4adf9d 100644 --- a/src/NHibernate.Test/NHibernate.Test.csproj +++ b/src/NHibernate.Test/NHibernate.Test.csproj @@ -582,6 +582,7 @@ + diff --git a/src/NHibernate/Mapping/ByCode/IJoinMapper.cs b/src/NHibernate/Mapping/ByCode/IJoinMapper.cs index e73ea8a6667..cf880907cb4 100644 --- a/src/NHibernate/Mapping/ByCode/IJoinMapper.cs +++ b/src/NHibernate/Mapping/ByCode/IJoinMapper.cs @@ -13,7 +13,7 @@ public interface IJoinAttributesMapper : IEntitySqlsMapper void Fetch(FetchKind fetchMode); } - public interface IJoinMapper : IJoinAttributesMapper, ICollectionPropertiesContainerMapper, IBasePlainPropertyContainerMapper { } + public interface IJoinMapper : IJoinAttributesMapper, IPropertyContainerMapper { } public interface IJoinAttributesMapper : IEntitySqlsMapper where TEntity : class { diff --git a/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinCustomizer.cs b/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinCustomizer.cs index b6dfd2b0f2f..a7946306ea0 100644 --- a/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinCustomizer.cs +++ b/src/NHibernate/Mapping/ByCode/Impl/CustomizersImpl/JoinCustomizer.cs @@ -132,6 +132,14 @@ protected override void RegisterComponentMapping(Expression(Expression> property + , Action> mapping) + { + MemberInfo member = TypeExtensions.DecodeMemberAccessExpression(property); + ExplicitDeclarationsHolder.AddAsPropertySplit(new SplitDefinition(typeof(TEntity), splitGroupId, member)); + base.RegisterDynamicComponentMapping(property, mapping); + } + protected override void RegisterManyToOneMapping(Expression> property, Action mapping) { MemberInfo member = TypeExtensions.DecodeMemberAccessExpression(property); diff --git a/src/NHibernate/Mapping/ByCode/ModelMapper.cs b/src/NHibernate/Mapping/ByCode/ModelMapper.cs index a79e167efd6..650dbff79a5 100644 --- a/src/NHibernate/Mapping/ByCode/ModelMapper.cs +++ b/src/NHibernate/Mapping/ByCode/ModelMapper.cs @@ -864,6 +864,10 @@ private void MapSplitProperties(System.Type propertiesContainerType, IEnumerable { MapComponent(member, memberPath, propertyType, propertiesContainer, propertiesContainerType); } + else if (modelInspector.IsDynamicComponent(member)) + { + MapDynamicComponent(member, memberPath, propertyType, propertiesContainer); + } else { MapProperty(member, memberPath, propertiesContainer); From 2b56cc17657b8a34580b8fbb30eac594f7859d38 Mon Sep 17 00:00:00 2001 From: Radim-Kohler Date: Tue, 28 Oct 2014 08:26:17 +0100 Subject: [PATCH 2/2] Introduced 6 test checking that JOIN adjustments properly assign hbmProperties to root or joined table --- .../JoinDynamicComponentTests.cs | 142 ++++++++++++++++-- 1 file changed, 133 insertions(+), 9 deletions(-) diff --git a/src/NHibernate.Test/MappingByCode/ExplicitMappingTests/JoinDynamicComponentTests.cs b/src/NHibernate.Test/MappingByCode/ExplicitMappingTests/JoinDynamicComponentTests.cs index f1a3c4c6c78..5a8f6c38ee9 100644 --- a/src/NHibernate.Test/MappingByCode/ExplicitMappingTests/JoinDynamicComponentTests.cs +++ b/src/NHibernate.Test/MappingByCode/ExplicitMappingTests/JoinDynamicComponentTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Linq; using NHibernate.Cfg.MappingSchema; using NHibernate.Mapping.ByCode; using NHibernate.Mapping.ByCode.Conformist; @@ -13,7 +14,7 @@ public class JoinDynamicComponentTests public class MyClass { public virtual int Code { get; set; } - public virtual string Name { get; set; } + public virtual string JoinedName { get; set; } public virtual MyOther Relation { get; set; } public virtual MyOther JoinedRelation { get; set; } public virtual IDictionary Attributes { get; set; } @@ -29,8 +30,9 @@ public class MyClassMap : ClassMapping { public MyClassMap() { - - this.Component(p => p.Attributes, + // basic table related properties + ManyToOne(x => x.Relation); + Component(p => p.Attributes, new { IsVisible = false, @@ -43,11 +45,12 @@ public MyClassMap() m.Property(p => p.Hash); m.ManyToOne(p => p.Reference); }); - Property(x => x.Code); + + // joined table stuff Join("JoinedAttributes", x => { - x.Property(p => p.Name); + x.Property(p => p.JoinedName); x.Component(p => p.JoinedAttributes, new { @@ -63,13 +66,134 @@ public MyClassMap() }); x.ManyToOne(p => p.JoinedRelation); }); - - ManyToOne(x => x.Relation); } } + protected HbmClass CompileClassMapping() + { + var mapper = new ModelMapper(); + mapper.AddMapping(typeof(MyClassMap)); + + var hbmMapping = mapper.CompileMappingFor(new[] { typeof(MyClass) }); + var hbmClass = hbmMapping.RootClasses[0]; + + return hbmClass; + } + [Test] - public void JoinedDynamicComponentShouldBeNestedInJoin() + public void WhenPropertyIsMappedOnRootThenItBelonsToRootTable() + { + // + var hbmClass = CompileClassMapping(); + hbmClass.Should().Not.Be.Null(); + + var rootProperties = hbmClass.Properties; + // p.Name == "Code"); + + hbmPropCode.Should().Not.Be.Null(); + hbmPropCode.Should().Be.OfType(); + } + + [Test] + public void WhenDynamicComponentIsMappedOnRootThenItBelonsToRootTable() + { + // + var hbmClass = CompileClassMapping(); + hbmClass.Should().Not.Be.Null(); + + var rootProperties = hbmClass.Properties; + // p.Name == "Attributes") + ; + + hbmPropAttributes.Should().Not.Be.Null(); + hbmPropAttributes.Should().Be.OfType(); + } + + [Test] + public void WhenRelationIsMappedOnRootThenItBelonsToRootTable() + { + // + var hbmClass = CompileClassMapping(); + hbmClass.Should().Not.Be.Null(); + + var rootProperties = hbmClass.Properties; + // p.Name == "Relation"); + + hbmPropRelation.Should().Not.Be.Null(); + hbmPropRelation.Should().Be.OfType(); + } + + [Test] + public void WhenJoinedPropertyIsMappedOnJoinThenItBelonsToJoinTable() + { + // + var hbmClass = CompileClassMapping(); + hbmClass.Should().Not.Be.Null(); + + // + var hbmJoined = hbmClass.Joins.FirstOrDefault(); + hbmJoined.Should().Not.Be.Null(); + + var rootProperties = hbmJoined.Properties; + // + // p.Name == "JoinedName"); + + hbmPropJoinedName.Should().Not.Be.Null(); + hbmPropJoinedName.Should().Be.OfType(); + } + + [Test] + public void WhenJoinedRelationIsMappedOnJoinThenItBelonsToJoinTable() + { + // + var hbmClass = CompileClassMapping(); + hbmClass.Should().Not.Be.Null(); + + // + var hbmJoined = hbmClass.Joins.FirstOrDefault(); + hbmJoined.Should().Not.Be.Null(); + + var rootProperties = hbmJoined.Properties; + // + // p.Name == "JoinedRelation"); + + hbmPropJoinedRelation.Should().Not.Be.Null(); + hbmPropJoinedRelation.Should().Be.OfType(); + } + + [Test] + public void WhenJoinedDynamicComponentIsMappedOnJoinThenItBelonsToJoinTable() + { + // + var hbmClass = CompileClassMapping(); + hbmClass.Should().Not.Be.Null(); + + // + var hbmJoined = hbmClass.Joins.FirstOrDefault(); + hbmJoined.Should().Not.Be.Null(); + + var rootProperties = hbmJoined.Properties; + // + // + var hbmPropJoinedAttributes = rootProperties + .FirstOrDefault(p => p.Name == "JoinedAttributes"); + + hbmPropJoinedAttributes.Should().Not.Be.Null(); + hbmPropJoinedAttributes.Should().Be.OfType(); + } + + // [Test] + public void Expected_XML_Result() { var mapper = new ModelMapper(); mapper.AddMapping(typeof(MyClassMap)); @@ -90,7 +214,7 @@ public void JoinedDynamicComponentShouldBeNestedInJoin() - +