From da28409bb37b1f988d688871a682930558d959a7 Mon Sep 17 00:00:00 2001 From: Jeff Hagen Date: Mon, 2 Dec 2024 09:53:12 -0500 Subject: [PATCH 1/6] Allow specification of in subclasses. --- .../Mapping/StoredProcedureTests.cs | 55 ++++++++++++++++++- src/FluentNHibernate/Mapping/SubclassMap.cs | 4 +- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/StoredProcedureTests.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/StoredProcedureTests.cs index 1f40610eb..d9e9ceb4e 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/StoredProcedureTests.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/StoredProcedureTests.cs @@ -1,4 +1,6 @@ -using NUnit.Framework; +using System; +using FluentNHibernate.Mapping; +using NUnit.Framework; namespace FluentNHibernate.Testing.DomainModel.Mapping; @@ -56,4 +58,55 @@ public void Can_specify_sql_delete_all() .Element("class/sql-delete-all") .ValueEquals("Delete ABC"); } + + [Test] + public void Can_specify_sql_insert_for_subclass() + { + var check = "Insert ABC"; + CreateMappingTester(x => x.SqlInsert(check)) + .Element("//subclass/sql-insert") + .ValueEquals(check); + } + + [Test] + public void Can_specify_sql_update_for_subclass() + { + var check = "Update ABC"; + CreateMappingTester(x => x.SqlUpdate(check)) + .Element("//subclass/sql-update") + .ValueEquals(check); + } + + [Test] + public void Can_specify_sql_delete_for_subclass() + { + var check = "Delete ABC"; + CreateMappingTester(x => x.SqlDelete(check)) + .Element("//subclass/sql-delete") + .ValueEquals(check); + } + + [Test] + public void Can_specify_sql_delete_all_for_subclass() + { + var check = "Delete ABC"; + CreateMappingTester(x => x.SqlDeleteAll(check)) + .Element("//subclass/sql-delete") + .ValueEquals(check); + } + + private MappingTester CreateMappingTester(Action> subclassMap) + { + return new MappingTester() + .SubClassMapping(sc => + { + sc.Map(x => x.SubclassProperty); + subclassMap.Invoke(sc); + }) + .ForMapping(m => + { + m.DiscriminateSubClassesOnColumn("test"); + m.Id(x => x.Id); + }); + } } diff --git a/src/FluentNHibernate/Mapping/SubclassMap.cs b/src/FluentNHibernate/Mapping/SubclassMap.cs index 058624d1e..0e279b554 100644 --- a/src/FluentNHibernate/Mapping/SubclassMap.cs +++ b/src/FluentNHibernate/Mapping/SubclassMap.cs @@ -327,9 +327,11 @@ SubclassMapping IIndeterminateSubclassMappingProvider.GetSubclassMapping(Subclas case MappingProviderStore.ProviderType.Any: mapping.AddAny(((IAnyMappingProvider)mappingProviderObj).GetAnyMapping()); break; + case MappingProviderStore.ProviderType.StoredProcedure: + mapping.AddStoredProcedure(((IStoredProcedureMappingProvider)mappingProviderObj).GetStoredProcedureMapping()); + break; case MappingProviderStore.ProviderType.Subclass: case MappingProviderStore.ProviderType.Filter: - case MappingProviderStore.ProviderType.StoredProcedure: case MappingProviderStore.ProviderType.Join: case MappingProviderStore.ProviderType.Identity: case MappingProviderStore.ProviderType.CompositeId: From d777f6aa3871a6454ef502794b06beb02273dc67 Mon Sep 17 00:00:00 2001 From: Jeff Hagen Date: Tue, 10 Jun 2025 16:27:52 -0400 Subject: [PATCH 2/6] fix unit test --- .../DomainModel/Mapping/StoredProcedureTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/StoredProcedureTests.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/StoredProcedureTests.cs index d9e9ceb4e..7e9997818 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/StoredProcedureTests.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/StoredProcedureTests.cs @@ -91,7 +91,7 @@ public void Can_specify_sql_delete_all_for_subclass() { var check = "Delete ABC"; CreateMappingTester(x => x.SqlDeleteAll(check)) - .Element("//subclass/sql-delete") + .Element("//subclass/sql-delete-all") .ValueEquals(check); } From 1684aeb0539821e04e699e0eb27e3a818d31452a Mon Sep 17 00:00:00 2001 From: Jeff Hagen Date: Tue, 10 Jun 2025 16:38:35 -0400 Subject: [PATCH 3/6] Make deepsource happy --- src/FluentNHibernate/Mapping/SubclassMap.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/FluentNHibernate/Mapping/SubclassMap.cs b/src/FluentNHibernate/Mapping/SubclassMap.cs index 0e279b554..370a33728 100644 --- a/src/FluentNHibernate/Mapping/SubclassMap.cs +++ b/src/FluentNHibernate/Mapping/SubclassMap.cs @@ -330,15 +330,6 @@ SubclassMapping IIndeterminateSubclassMappingProvider.GetSubclassMapping(Subclas case MappingProviderStore.ProviderType.StoredProcedure: mapping.AddStoredProcedure(((IStoredProcedureMappingProvider)mappingProviderObj).GetStoredProcedureMapping()); break; - case MappingProviderStore.ProviderType.Subclass: - case MappingProviderStore.ProviderType.Filter: - case MappingProviderStore.ProviderType.Join: - case MappingProviderStore.ProviderType.Identity: - case MappingProviderStore.ProviderType.CompositeId: - case MappingProviderStore.ProviderType.NaturalId: - case MappingProviderStore.ProviderType.Version: - case MappingProviderStore.ProviderType.Discriminator: - case MappingProviderStore.ProviderType.Tupilizer: default: throw new Exception("Internal Error"); } From c2af28e9e53aedae53570ad37001210e63bcd2be Mon Sep 17 00:00:00 2001 From: Jeff Hagen Date: Wed, 11 Jun 2025 13:28:02 -0400 Subject: [PATCH 4/6] Add support for tuplizers on subclass and component --- .../Mapping/ComponentPartTester.cs | 36 +++++++++++++++++-- .../DomainModel/Mapping/MappingTester.cs | 6 ++-- .../DomainModel/Mapping/SubClassTester.cs | 25 ++++++++++++- .../Mapping/UnionSubclassTester.cs | 22 ++++++++++++ src/FluentNHibernate/Mapping/ClassMap.cs | 13 ++----- .../Mapping/ClasslikeMapBase.cs | 12 +++++++ src/FluentNHibernate/Mapping/ComponentPart.cs | 9 +++++ .../Mapping/ComponentPartBase.cs | 4 ++- src/FluentNHibernate/Mapping/SubClassPart.cs | 1 - src/FluentNHibernate/Mapping/SubclassMap.cs | 12 +++++++ .../ClassBased/ClassMappingBase.cs | 2 +- .../ClassBased/ComponentMapping.cs | 5 +++ .../ClassBased/SubclassMapping.cs | 5 +++ .../Output/BaseXmlComponentWriter.cs | 8 +++++ .../MappingModel/Output/XmlSubclassWriter.cs | 8 +++++ 15 files changed, 148 insertions(+), 20 deletions(-) diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/ComponentPartTester.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/ComponentPartTester.cs index 14567a1d2..4354d4f06 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/ComponentPartTester.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/ComponentPartTester.cs @@ -1,4 +1,6 @@ -using NUnit.Framework; +using System; +using FluentNHibernate.MappingModel; +using NUnit.Framework; namespace FluentNHibernate.Testing.DomainModel.Mapping; @@ -103,6 +105,34 @@ public void ComponentSetsClass() .ForMapping(m => m.Component(x => x.Component, c => c.Map(x => x.Name))) .Element("class/component").HasAttribute("class", typeof(ComponentTarget).AssemblyQualifiedName); - } - + } + + [Test] + public void ComponentCanSetTuplizer() + { + Type tuplizerType = typeof(NHibernate.Tuple.Entity.PocoEntityTuplizer); + new MappingTester() + .ForMapping(m => + m.Component(x => x.Component, c => c.Tuplizer(TuplizerMode.Poco, tuplizerType))) + .Element("class/component/tuplizer") + .HasAttribute("class", tuplizerType.AssemblyQualifiedName) + .HasAttribute("entity-mode", nameof(TuplizerMode.Poco).ToLower()); + } + + [Test] + public void ComponentCanSetTuplizerInCorrectOrderRegardlessOfDeclaration() + { + Type tuplizerType = typeof(NHibernate.Tuple.Entity.PocoEntityTuplizer); + new MappingTester() + .ForMapping(m => + m.Component(x => x.Component, c => + { + c.Map(x => x.Name); + c.ParentReference(x => x.MyParent); + c.Tuplizer(TuplizerMode.Poco, tuplizerType); + })) + .Element("class/component/tuplizer").Exists().ShouldBeInParentAtPosition(0) + .Element("class/component/parent").Exists().ShouldBeInParentAtPosition(1) + .Element("class/component/property").Exists().ShouldBeInParentAtPosition(2); + } } diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/MappingTester.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/MappingTester.cs index 7c2878f50..f1aaa7fb7 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/MappingTester.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/MappingTester.cs @@ -48,7 +48,7 @@ public virtual MappingTester SubClassMapping(Action ForMapping(Action> mappingAction) { var classMap = new ClassMap(); @@ -189,7 +189,9 @@ public virtual MappingTester ShouldBeInParentAtPosition(int elementPosition) else { XmlElement elementAtPosition = (XmlElement)currentElement.ParentNode.ChildNodes.Item(elementPosition); - Assert.That(elementAtPosition, Is.EqualTo(currentElement), $"Expected '{currentElement.Name}' but was '{elementAtPosition.Name}'"); + // Assert.That(elementWithoutChildren0, IsEqualTo(elementWithoutChildren1)) always returns true (it defaults + // to the NUnit IEnumerable comparer, which returns equal cause both don't have child nodes). + Assert.That(elementAtPosition?.OuterXml, Is.EqualTo(currentElement.OuterXml), $"Expected '{currentElement.Name}' but was '{elementAtPosition.Name}'"); } return this; diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/SubClassTester.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/SubClassTester.cs index d378d2287..604cb12ed 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/SubClassTester.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/SubClassTester.cs @@ -1,6 +1,8 @@ +using System; using FluentNHibernate.Conventions; using FluentNHibernate.Conventions.Instances; using FluentNHibernate.Mapping; +using FluentNHibernate.MappingModel; using NUnit.Framework; namespace FluentNHibernate.Testing.DomainModel.Mapping; @@ -590,7 +592,28 @@ public void SubSubclassOneToManyReferenceHasConventionApplied() .HasAttribute("foreign-key", "test_fk"); } - + + [Test] + public void SubclassCanSetTuplizerInCorrectOrder() + { + Type tuplizerType = typeof(NHibernate.Tuple.Entity.PocoEntityTuplizer); + new MappingTester() + .SubClassMapping(m => + { + m.Map(x => x.SubclassProperty); + m.Tuplizer(TuplizerMode.Poco, tuplizerType); + m.DiscriminatorValue("test"); + }) + .ForMapping(m => + { + m.DiscriminateSubClassesOnColumn("test_column"); + m.Id(x => x.Id); + m.Tuplizer(TuplizerMode.Poco, tuplizerType); + }) + .Element("class/subclass/tuplizer").Exists().ShouldBeInParentAtPosition(0) + .Element("class/tuplizer").Exists().ShouldBeInParentAtPosition(0); + } + public class TestPropertyConvention : IPropertyConvention { public void Apply(IPropertyInstance instance) diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/UnionSubclassTester.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/UnionSubclassTester.cs index e5987293d..efb0e6efb 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/UnionSubclassTester.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/UnionSubclassTester.cs @@ -1,3 +1,5 @@ +using System; +using FluentNHibernate.MappingModel; using NUnit.Framework; namespace FluentNHibernate.Testing.DomainModel.Mapping; @@ -44,4 +46,24 @@ public void ShouldAllowEntityNameToBeSetOnUnionSubclasses() }).Element("class/union-subclass") .HasAttribute("entity-name", "name"); } + + [Test] + public void SubclassCanSetTuplizerInCorrectOrder() + { + Type tuplizerType = typeof(NHibernate.Tuple.Entity.PocoEntityTuplizer); + new MappingTester() + .SubClassMapping(m => + { + m.Map(x => x.SubclassProperty); + m.Tuplizer(TuplizerMode.Poco, tuplizerType); + }) + .ForMapping(m => + { + m.UseUnionSubclassForInheritanceMapping(); + m.Id(x => x.Id); + m.Tuplizer(TuplizerMode.Poco, tuplizerType); + }) + .Element("class/union-subclass/tuplizer").Exists().ShouldBeInParentAtPosition(0) + .Element("class/tuplizer").Exists().ShouldBeInParentAtPosition(0); + } } diff --git a/src/FluentNHibernate/Mapping/ClassMap.cs b/src/FluentNHibernate/Mapping/ClassMap.cs index 0e1991659..7d86203d3 100644 --- a/src/FluentNHibernate/Mapping/ClassMap.cs +++ b/src/FluentNHibernate/Mapping/ClassMap.cs @@ -583,17 +583,8 @@ public ClassMap ApplyFilter(string name) /// /// Tuplizer entity-mode /// Tuplizer type - public TuplizerPart Tuplizer(TuplizerMode mode, Type tuplizerType) - { - providers.TuplizerMapping = new TuplizerMapping(); - providers.TuplizerMapping.Set(x => x.Mode, Layer.UserSupplied, mode); - providers.TuplizerMapping.Set(x => x.Type, Layer.UserSupplied, new TypeReference(tuplizerType)); - - return new TuplizerPart(providers.TuplizerMapping) - .Type(tuplizerType) - .Mode(mode); - } - + public TuplizerPart Tuplizer(TuplizerMode mode, Type tuplizerType) => CreateTuplizerPart(mode, tuplizerType); + ClassMapping IMappingProvider.GetClassMapping() { var mapping = new ClassMapping(attributes.Clone()); diff --git a/src/FluentNHibernate/Mapping/ClasslikeMapBase.cs b/src/FluentNHibernate/Mapping/ClasslikeMapBase.cs index 4f9b87065..812016fa7 100644 --- a/src/FluentNHibernate/Mapping/ClasslikeMapBase.cs +++ b/src/FluentNHibernate/Mapping/ClasslikeMapBase.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using FluentNHibernate.Mapping.Providers; +using FluentNHibernate.MappingModel; using FluentNHibernate.Utils; namespace FluentNHibernate.Mapping; @@ -438,6 +439,17 @@ protected StoredProcedurePart StoredProcedure(string element, string innerText) providers.StoredProcedures.Add(part); return part; } + + protected TuplizerPart CreateTuplizerPart(TuplizerMode mode, Type tuplizerType) + { + providers.TuplizerMapping = new TuplizerMapping(); + providers.TuplizerMapping.Set(x => x.Mode, Layer.UserSupplied, mode); + providers.TuplizerMapping.Set(x => x.Type, Layer.UserSupplied, new TypeReference(tuplizerType)); + + return new TuplizerPart(providers.TuplizerMapping) + .Type(tuplizerType) + .Mode(mode); + } internal IEnumerable Properties => providers.Properties; diff --git a/src/FluentNHibernate/Mapping/ComponentPart.cs b/src/FluentNHibernate/Mapping/ComponentPart.cs index ba95ab242..e46482e01 100644 --- a/src/FluentNHibernate/Mapping/ComponentPart.cs +++ b/src/FluentNHibernate/Mapping/ComponentPart.cs @@ -41,6 +41,15 @@ public ComponentPart LazyLoad() nextBool = true; return this; } + + /// + /// Configures the tuplizer for this component. The tuplizer defines how to transform + /// a Property-Value to its persistent representation, and viceversa a Column-Value + /// to its in-memory representation, and the EntityMode defines which tuplizer is in use. + /// + /// Tuplizer entity-mode + /// Tuplizer type + public TuplizerPart Tuplizer(TuplizerMode mode, Type tuplizerType) => CreateTuplizerPart(mode, tuplizerType); IComponentMapping IComponentMappingProvider.GetComponentMapping() { diff --git a/src/FluentNHibernate/Mapping/ComponentPartBase.cs b/src/FluentNHibernate/Mapping/ComponentPartBase.cs index 95efcde5b..30b362e04 100644 --- a/src/FluentNHibernate/Mapping/ComponentPartBase.cs +++ b/src/FluentNHibernate/Mapping/ComponentPartBase.cs @@ -166,7 +166,9 @@ protected ComponentMapping CreateComponentMapping() if (member is not null) mapping.Set(x => x.Name, Layer.Defaults, member.Name); - + + mapping.Set(x => x.Tuplizer, Layer.UserSupplied, providers.TuplizerMapping); + foreach (var property in providers.Properties) mapping.AddProperty(property.GetPropertyMapping()); diff --git a/src/FluentNHibernate/Mapping/SubClassPart.cs b/src/FluentNHibernate/Mapping/SubClassPart.cs index f641fa43e..4bc8ad060 100644 --- a/src/FluentNHibernate/Mapping/SubClassPart.cs +++ b/src/FluentNHibernate/Mapping/SubClassPart.cs @@ -4,7 +4,6 @@ using FluentNHibernate.Mapping.Providers; using FluentNHibernate.MappingModel; using FluentNHibernate.MappingModel.ClassBased; -using FluentNHibernate.Utils; namespace FluentNHibernate.Mapping; diff --git a/src/FluentNHibernate/Mapping/SubclassMap.cs b/src/FluentNHibernate/Mapping/SubclassMap.cs index 370a33728..33d2b0f0c 100644 --- a/src/FluentNHibernate/Mapping/SubclassMap.cs +++ b/src/FluentNHibernate/Mapping/SubclassMap.cs @@ -277,6 +277,15 @@ public void Extends(Type type) { attributes.Set("Extends", Layer.UserSupplied, type); } + + /// + /// Configures the tuplizer for this entity. The tuplizer defines how to transform + /// a Property-Value to its persistent representation, and viceversa a Column-Value + /// to its in-memory representation, and the EntityMode defines which tuplizer is in use. + /// + /// Tuplizer entity-mode + /// Tuplizer type + public TuplizerPart Tuplizer(TuplizerMode mode, Type tuplizerType) => CreateTuplizerPart(mode, tuplizerType); SubclassMapping IIndeterminateSubclassMappingProvider.GetSubclassMapping(SubclassType type) { @@ -330,6 +339,9 @@ SubclassMapping IIndeterminateSubclassMappingProvider.GetSubclassMapping(Subclas case MappingProviderStore.ProviderType.StoredProcedure: mapping.AddStoredProcedure(((IStoredProcedureMappingProvider)mappingProviderObj).GetStoredProcedureMapping()); break; + case MappingProviderStore.ProviderType.Tupilizer: + mapping.Set(y => y.Tuplizer, Layer.Defaults, (TuplizerMapping)mappingProviderObj); + break; default: throw new Exception("Internal Error"); } diff --git a/src/FluentNHibernate/MappingModel/ClassBased/ClassMappingBase.cs b/src/FluentNHibernate/MappingModel/ClassBased/ClassMappingBase.cs index cab74d169..7ffd749e8 100644 --- a/src/FluentNHibernate/MappingModel/ClassBased/ClassMappingBase.cs +++ b/src/FluentNHibernate/MappingModel/ClassBased/ClassMappingBase.cs @@ -17,7 +17,7 @@ public abstract class ClassMappingBase(AttributeStore attributes) : MappingBase, public override void AcceptVisitor(IMappingModelVisitor visitor) { mappedMembers.AcceptVisitor(visitor); - + foreach (var subclass in Subclasses) visitor.Visit(subclass); } diff --git a/src/FluentNHibernate/MappingModel/ClassBased/ComponentMapping.cs b/src/FluentNHibernate/MappingModel/ClassBased/ComponentMapping.cs index dabdf523f..7048493c9 100644 --- a/src/FluentNHibernate/MappingModel/ClassBased/ComponentMapping.cs +++ b/src/FluentNHibernate/MappingModel/ClassBased/ComponentMapping.cs @@ -25,6 +25,9 @@ public override void AcceptVisitor(IMappingModelVisitor visitor) { visitor.ProcessComponent(this); + if (Tuplizer is not null) + visitor.Visit(Tuplizer); + base.AcceptVisitor(visitor); } @@ -39,6 +42,8 @@ public override void AcceptVisitor(IMappingModelVisitor visitor) public TypeReference Class => attributes.GetOrDefault(); public bool Lazy => attributes.GetOrDefault(); + + public TuplizerMapping Tuplizer => attributes.GetOrDefault(); public bool Equals(ComponentMapping other) { diff --git a/src/FluentNHibernate/MappingModel/ClassBased/SubclassMapping.cs b/src/FluentNHibernate/MappingModel/ClassBased/SubclassMapping.cs index b453691c1..ebeec9d7e 100644 --- a/src/FluentNHibernate/MappingModel/ClassBased/SubclassMapping.cs +++ b/src/FluentNHibernate/MappingModel/ClassBased/SubclassMapping.cs @@ -27,6 +27,9 @@ public override void AcceptVisitor(IMappingModelVisitor visitor) { visitor.ProcessSubclass(this); + if (Tuplizer is not null) + visitor.Visit(Tuplizer); + if (SubclassType == SubclassType.JoinedSubclass && Key is not null) visitor.Visit(Key); @@ -66,6 +69,8 @@ public override void AcceptVisitor(IMappingModelVisitor visitor) public TypeReference Persister => attributes.GetOrDefault(); public int BatchSize => attributes.GetOrDefault(); + + public TuplizerMapping Tuplizer => attributes.GetOrDefault(); public void OverrideAttributes(AttributeStore store) { diff --git a/src/FluentNHibernate/MappingModel/Output/BaseXmlComponentWriter.cs b/src/FluentNHibernate/MappingModel/Output/BaseXmlComponentWriter.cs index 9f86bc6f8..d292c3ee3 100644 --- a/src/FluentNHibernate/MappingModel/Output/BaseXmlComponentWriter.cs +++ b/src/FluentNHibernate/MappingModel/Output/BaseXmlComponentWriter.cs @@ -47,4 +47,12 @@ public override void Visit(ParentMapping parentMapping) document.ImportAndAppendChild(parentXml); } + + public override void Visit(TuplizerMapping mapping) + { + var writer = serviceLocator.GetWriter(); + var filterXml = writer.Write(mapping); + + document.ImportAndAppendChild(filterXml); + } } diff --git a/src/FluentNHibernate/MappingModel/Output/XmlSubclassWriter.cs b/src/FluentNHibernate/MappingModel/Output/XmlSubclassWriter.cs index 538b65eef..f40382894 100644 --- a/src/FluentNHibernate/MappingModel/Output/XmlSubclassWriter.cs +++ b/src/FluentNHibernate/MappingModel/Output/XmlSubclassWriter.cs @@ -104,4 +104,12 @@ public override void Visit(JoinMapping joinMapping) document.ImportAndAppendChild(xml); } + + public override void Visit(TuplizerMapping mapping) + { + var writer = serviceLocator.GetWriter(); + var filterXml = writer.Write(mapping); + + document.ImportAndAppendChild(filterXml); + } } From b37464f7fd369b1688a07cd70f8bef9411476f92 Mon Sep 17 00:00:00 2001 From: Alex Zaytsev Date: Thu, 31 Jul 2025 13:49:10 +1000 Subject: [PATCH 5/6] Use same as --- .../DomainModel/Mapping/MappingTester.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/MappingTester.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/MappingTester.cs index f1aaa7fb7..9caebece9 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/MappingTester.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/MappingTester.cs @@ -48,7 +48,7 @@ public virtual MappingTester SubClassMapping(Action ForMapping(Action> mappingAction) { var classMap = new ClassMap(); @@ -189,9 +189,7 @@ public virtual MappingTester ShouldBeInParentAtPosition(int elementPosition) else { XmlElement elementAtPosition = (XmlElement)currentElement.ParentNode.ChildNodes.Item(elementPosition); - // Assert.That(elementWithoutChildren0, IsEqualTo(elementWithoutChildren1)) always returns true (it defaults - // to the NUnit IEnumerable comparer, which returns equal cause both don't have child nodes). - Assert.That(elementAtPosition?.OuterXml, Is.EqualTo(currentElement.OuterXml), $"Expected '{currentElement.Name}' but was '{elementAtPosition.Name}'"); + Assert.That(elementAtPosition, Is.SameAs(currentElement), $"Expected '{currentElement.Name}' but was '{elementAtPosition.Name}'"); } return this; From 0d676f4682ba6d1a31f920d77359134b9a09374b Mon Sep 17 00:00:00 2001 From: Alex Zaytsev Date: Thu, 31 Jul 2025 13:53:08 +1000 Subject: [PATCH 6/6] whitespace fixes --- .../DomainModel/Mapping/ComponentPartTester.cs | 2 +- src/FluentNHibernate/Mapping/ComponentPartBase.cs | 4 ++-- .../MappingModel/ClassBased/ClassMappingBase.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/ComponentPartTester.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/ComponentPartTester.cs index 4354d4f06..34130ac6e 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/ComponentPartTester.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/ComponentPartTester.cs @@ -106,7 +106,7 @@ public void ComponentSetsClass() m.Component(x => x.Component, c => c.Map(x => x.Name))) .Element("class/component").HasAttribute("class", typeof(ComponentTarget).AssemblyQualifiedName); } - + [Test] public void ComponentCanSetTuplizer() { diff --git a/src/FluentNHibernate/Mapping/ComponentPartBase.cs b/src/FluentNHibernate/Mapping/ComponentPartBase.cs index 30b362e04..5ece64ee6 100644 --- a/src/FluentNHibernate/Mapping/ComponentPartBase.cs +++ b/src/FluentNHibernate/Mapping/ComponentPartBase.cs @@ -166,9 +166,9 @@ protected ComponentMapping CreateComponentMapping() if (member is not null) mapping.Set(x => x.Name, Layer.Defaults, member.Name); - + mapping.Set(x => x.Tuplizer, Layer.UserSupplied, providers.TuplizerMapping); - + foreach (var property in providers.Properties) mapping.AddProperty(property.GetPropertyMapping()); diff --git a/src/FluentNHibernate/MappingModel/ClassBased/ClassMappingBase.cs b/src/FluentNHibernate/MappingModel/ClassBased/ClassMappingBase.cs index 7ffd749e8..cab74d169 100644 --- a/src/FluentNHibernate/MappingModel/ClassBased/ClassMappingBase.cs +++ b/src/FluentNHibernate/MappingModel/ClassBased/ClassMappingBase.cs @@ -17,7 +17,7 @@ public abstract class ClassMappingBase(AttributeStore attributes) : MappingBase, public override void AcceptVisitor(IMappingModelVisitor visitor) { mappedMembers.AcceptVisitor(visitor); - + foreach (var subclass in Subclasses) visitor.Visit(subclass); }