From d9621a8e3dff4438cf961059b61af1682927757d Mon Sep 17 00:00:00 2001 From: visubesy Date: Mon, 4 Jul 2016 18:56:38 +0200 Subject: [PATCH 1/4] Don't use only name for PropertyPart.CustomType - Use the constructor of TypeReference with Type argument instead of the constructor with string argument in the overloads of CustomType in PropertyPart where an explicit Type is passed. - This fixes the problem that Fluent NHibernate may map a wrong type for a property although an explicit type was passed to CustomType. This problem can happen if there are two types with names which only differ in upper / lower case. Such similar type names can e.g. be caused by obfuscation tools. --- src/FluentNHibernate/Mapping/PropertyPart.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/FluentNHibernate/Mapping/PropertyPart.cs b/src/FluentNHibernate/Mapping/PropertyPart.cs index 38b15779b..c4df75e3f 100644 --- a/src/FluentNHibernate/Mapping/PropertyPart.cs +++ b/src/FluentNHibernate/Mapping/PropertyPart.cs @@ -183,7 +183,9 @@ public PropertyPart CustomType(Type type) if (typeof(ICompositeUserType).IsAssignableFrom(type)) AddColumnsFromCompositeUserType(type); - return CustomType(TypeMapping.GetTypeString(type)); + attributes.Set("Type", Layer.UserSupplied, new TypeReference(type)); + + return this; } /// @@ -206,11 +208,7 @@ public PropertyPart CustomType(string type) public PropertyPart CustomType(Func typeFunc) { var type = typeFunc.Invoke(member.PropertyType); - - if (typeof(ICompositeUserType).IsAssignableFrom(type)) - AddColumnsFromCompositeUserType(type); - - return CustomType(TypeMapping.GetTypeString(type)); + return CustomType(type); } private void AddColumnsFromCompositeUserType(Type compositeUserType) From 767aea37a29d10f872183a1a2dc7e07cea659694 Mon Sep 17 00:00:00 2001 From: visubesy Date: Mon, 4 Jul 2016 19:15:00 +0200 Subject: [PATCH 2/4] Adapt tests to new behaviour of PropertyPart - The production code of the CustomType overloads of PropertyPart was changed to use a different constructor of TypeReference when an explicit Type was given. This caused two tests to fail although the code still should work correctly. - Change failing tests to expect the new behaviour. --- .../OverridingFluentInterface/PropertyConventionTests.cs | 2 +- .../DomainModel/Mapping/ClassMapConventionsTester.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FluentNHibernate.Testing/ConventionsTests/OverridingFluentInterface/PropertyConventionTests.cs b/src/FluentNHibernate.Testing/ConventionsTests/OverridingFluentInterface/PropertyConventionTests.cs index ed9db8238..54f9a5c6e 100644 --- a/src/FluentNHibernate.Testing/ConventionsTests/OverridingFluentInterface/PropertyConventionTests.cs +++ b/src/FluentNHibernate.Testing/ConventionsTests/OverridingFluentInterface/PropertyConventionTests.cs @@ -65,7 +65,7 @@ public void TypeShouldntBeOverwritten() Convention(x => x.CustomType()); - VerifyModel(x => x.Type.Name.ShouldEqual(typeof(CustomUserType).AssemblyQualifiedName)); + VerifyModel(x => x.Type.GetUnderlyingSystemType().ShouldEqual(typeof(CustomUserType))); } [Test] diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapConventionsTester.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapConventionsTester.cs index be0017494..1a312dc14 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapConventionsTester.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapConventionsTester.cs @@ -108,7 +108,7 @@ public void EnumsDontGetTypeOverriddenByConventionsIfExplicitlySet() { new MappingTester() .ForMapping(m => m.Map(x => x.Color).CustomType(typeof(int))) - .Element("class/property[@name='Color']").HasAttribute("type", typeof(int).Name); + .Element("class/property[@name='Color']").HasAttribute("type", typeof(int).AssemblyQualifiedName); } } } \ No newline at end of file From a0aa635e5d7f1411e8ce24d6daca084f8050dead Mon Sep 17 00:00:00 2001 From: visubesy Date: Mon, 17 Mar 2025 16:42:07 +0100 Subject: [PATCH 3/4] Fix deepsource complaint CS-R1064 --- src/FluentNHibernate/Mapping/PropertyPart.cs | 696 +++++++++---------- 1 file changed, 348 insertions(+), 348 deletions(-) diff --git a/src/FluentNHibernate/Mapping/PropertyPart.cs b/src/FluentNHibernate/Mapping/PropertyPart.cs index f30e731c5..740c25030 100644 --- a/src/FluentNHibernate/Mapping/PropertyPart.cs +++ b/src/FluentNHibernate/Mapping/PropertyPart.cs @@ -1,348 +1,348 @@ -using System; -using System.Diagnostics; -using FluentNHibernate.Mapping.Providers; -using FluentNHibernate.MappingModel; -using FluentNHibernate.Utils; -using NHibernate.Type; -using NHibernate.UserTypes; - -namespace FluentNHibernate.Mapping; - -public class PropertyPart : IPropertyMappingProvider -{ - readonly Member member; - readonly Type parentType; - readonly AttributeStore attributes = new AttributeStore(); - readonly AttributeStore columnAttributes = new AttributeStore(); - - bool nextBool = true; - - public PropertyPart(Member member, Type parentType) - { - Columns = new ColumnMappingCollection(this); - Access = new AccessStrategyBuilder(this, value => attributes.Set("Access", Layer.UserSupplied, value)); - Generated = new PropertyGeneratedBuilder(this, value => attributes.Set("Generated", Layer.UserSupplied, value)); - - this.member = member; - this.parentType = parentType; - - SetDefaultAccess(); - } - - void SetDefaultAccess() - { - var resolvedAccess = MemberAccessResolver.Resolve(member); - - if (resolvedAccess == Mapping.Access.Property || resolvedAccess == Mapping.Access.Unset) - return; // property is the default so we don't need to specify it - - attributes.Set("Access", Layer.Defaults, resolvedAccess.ToString()); - } - - /// - /// Specify if this property is database generated - /// - /// - /// Generated.Insert(); - /// - public PropertyGeneratedBuilder Generated { get; } - - /// - /// Specify the property column name - /// - /// Column name - public PropertyPart Column(string columnName) - { - Columns.Clear(); - Columns.Add(columnName); - return this; - } - - /// - /// Modify the columns collection - /// - public ColumnMappingCollection Columns { get; } - - /// - /// Set the access and naming strategy for this property. - /// - public AccessStrategyBuilder Access { get; } - - /// - /// Specify that this property is insertable - /// - public PropertyPart Insert() - { - attributes.Set("Insert", Layer.UserSupplied, nextBool); - nextBool = true; - - return this; - } - - /// - /// Specify that this property is updatable - /// - public PropertyPart Update() - { - attributes.Set("Update", Layer.UserSupplied, nextBool); - nextBool = true; - - return this; - } - - /// - /// Specify the column length - /// - /// Column length - public PropertyPart Length(int length) - { - columnAttributes.Set("Length", Layer.UserSupplied, length); - return this; - } - - /// - /// Specify the nullability of this property - /// - public PropertyPart Nullable() - { - columnAttributes.Set("NotNull", Layer.UserSupplied, !nextBool); - nextBool = true; - return this; - } - - /// - /// Specify that this property is read-only - /// - public PropertyPart ReadOnly() - { - attributes.Set("Insert", Layer.UserSupplied, !nextBool); - attributes.Set("Update", Layer.UserSupplied, !nextBool); - nextBool = true; - return this; - } - - /// - /// Specify the property formula - /// - /// Formula - public PropertyPart Formula(string formula) - { - attributes.Set("Formula", Layer.UserSupplied, formula); - return this; - } - - /// - /// Specify the lazy-loading behaviour - /// - public PropertyPart LazyLoad() - { - attributes.Set("Lazy", Layer.UserSupplied, nextBool); - nextBool = true; - return this; - } - - /// - /// Specify an index name - /// - /// Index name - public PropertyPart Index(string index) - { - columnAttributes.Set("Index", Layer.UserSupplied, index); - return this; - } - - /// - /// Specifies that a custom type (an implementation of ) should be used for this property for mapping it to/from one or more database columns whose format or type doesn't match this .NET property. - /// - /// A type which implements . - /// This property mapping to continue the method chain - public PropertyPart CustomType() - { - return CustomType(typeof(TCustomtype)); - } - - /// - /// Specifies that a custom type (an implementation of ) should be used for this property for mapping it to/from one or more database columns whose format or type doesn't match this .NET property. - /// - /// A type which implements . - /// This property mapping to continue the method chain - public PropertyPart CustomType(Type type) - { - if (typeof(ICompositeUserType).IsAssignableFrom(type)) - AddColumnsFromCompositeUserType(type); - - attributes.Set("Type", Layer.UserSupplied, new TypeReference(type)); - return this; - } - - /// - /// Specifies that a custom type (an implementation of ) should be used for this property for mapping it to/from one or more database columns whose format or type doesn't match this .NET property. - /// - /// A type which implements . - /// This property mapping to continue the method chain - public PropertyPart CustomType(string type) - { - attributes.Set("Type", Layer.UserSupplied, new TypeReference(type)); - - return this; - } - - /// - /// Specifies that a custom type (an implementation of ) should be used for this property for mapping it to/from one or more database columns whose format or type doesn't match this .NET property. - /// - /// A function which returns a type which implements . The argument of the function is the mapped property type - /// This property mapping to continue the method chain - public PropertyPart CustomType(Func typeFunc) - { - var type = typeFunc.Invoke(member.PropertyType); - return CustomType(type); - } - - void AddColumnsFromCompositeUserType(Type compositeUserType) - { - var inst = (ICompositeUserType)Activator.CreateInstance(compositeUserType); - - foreach (var name in inst.PropertyNames) - { - Columns.Add(name); - } - } - - /// - /// Specify a custom SQL type - /// - /// SQL type - public PropertyPart CustomSqlType(string sqlType) - { - columnAttributes.Set("SqlType", Layer.UserSupplied, sqlType); - return this; - } - - /// - /// Specify that this property has a unique constraint - /// - public PropertyPart Unique() - { - columnAttributes.Set("Unique", Layer.UserSupplied, nextBool); - nextBool = true; - return this; - } - - /// - /// Specify decimal precision - /// - /// Decimal precision - public PropertyPart Precision(int precision) - { - columnAttributes.Set("Precision", Layer.UserSupplied, precision); - return this; - } - - /// - /// Specify decimal scale - /// - /// Decimal scale - public PropertyPart Scale(int scale) - { - columnAttributes.Set("Scale", Layer.UserSupplied, scale); - return this; - } - - /// - /// Specify a default value - /// - /// Default value - public PropertyPart Default(string value) - { - columnAttributes.Set("Default", Layer.UserSupplied, value); - return this; - } - - /// - /// Specifies the name of a multi-column unique constraint. - /// - /// Name of constraint - public PropertyPart UniqueKey(string keyName) - { - columnAttributes.Set("UniqueKey", Layer.UserSupplied, keyName); - return this; - } - - /// - /// Specify that this property is optimistically locked - /// - public PropertyPart OptimisticLock() - { - attributes.Set("OptimisticLock", Layer.UserSupplied, nextBool); - nextBool = true; - return this; - } - - /// - /// Inverts the next boolean - /// - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - public PropertyPart Not - { - get - { - nextBool = !nextBool; - return this; - } - } - - /// - /// Specify a check constraint - /// - /// Constraint name - public PropertyPart Check(string constraint) - { - columnAttributes.Set("Check", Layer.UserSupplied, constraint); - return this; - } - - PropertyMapping IPropertyMappingProvider.GetPropertyMapping() - { - var mapping = new PropertyMapping(attributes.Clone()) - { - ContainingEntityType = parentType, - Member = member - }; - - if (Columns.Count == 0 && !mapping.IsSpecified("Formula")) - { - var columnMapping = new ColumnMapping(columnAttributes.Clone()); - columnMapping.Set(x => x.Name, Layer.Defaults, member.Name); - mapping.AddColumn(Layer.Defaults, columnMapping); - } - - foreach (var column in Columns) - mapping.AddColumn(Layer.UserSupplied, column.Clone()); - - foreach (var column in mapping.Columns) - { - if (member.PropertyType.IsNullableType() && member.PropertyType.IsEnum()) - column.Set(x => x.NotNull, Layer.Defaults, false); - - column.MergeAttributes(columnAttributes); - } - - mapping.Set(x => x.Name, Layer.Defaults, mapping.Member.Name); - mapping.Set(x => x.Type, Layer.Defaults, GetDefaultType()); - - return mapping; - } - - TypeReference GetDefaultType() - { - var type = new TypeReference(member.PropertyType); - - if (member.PropertyType.IsEnum()) - type = new TypeReference(typeof(EnumStringType<>).MakeGenericType(member.PropertyType)); - - if (member.PropertyType.IsNullableType() && member.PropertyType.IsEnum()) - type = new TypeReference(typeof(EnumStringType<>).MakeGenericType(member.PropertyType.GetGenericArguments()[0])); - - return type; - } -} \ No newline at end of file +using System; +using System.Diagnostics; +using FluentNHibernate.Mapping.Providers; +using FluentNHibernate.MappingModel; +using FluentNHibernate.Utils; +using NHibernate.Type; +using NHibernate.UserTypes; + +namespace FluentNHibernate.Mapping; + +public class PropertyPart : IPropertyMappingProvider +{ + readonly Member member; + readonly Type parentType; + readonly AttributeStore attributes = new(); + readonly AttributeStore columnAttributes = new(); + + bool nextBool = true; + + public PropertyPart(Member member, Type parentType) + { + Columns = new ColumnMappingCollection(this); + Access = new AccessStrategyBuilder(this, value => attributes.Set("Access", Layer.UserSupplied, value)); + Generated = new PropertyGeneratedBuilder(this, value => attributes.Set("Generated", Layer.UserSupplied, value)); + + this.member = member; + this.parentType = parentType; + + SetDefaultAccess(); + } + + void SetDefaultAccess() + { + var resolvedAccess = MemberAccessResolver.Resolve(member); + + if (resolvedAccess == Mapping.Access.Property || resolvedAccess == Mapping.Access.Unset) + return; // property is the default so we don't need to specify it + + attributes.Set("Access", Layer.Defaults, resolvedAccess.ToString()); + } + + /// + /// Specify if this property is database generated + /// + /// + /// Generated.Insert(); + /// + public PropertyGeneratedBuilder Generated { get; } + + /// + /// Specify the property column name + /// + /// Column name + public PropertyPart Column(string columnName) + { + Columns.Clear(); + Columns.Add(columnName); + return this; + } + + /// + /// Modify the columns collection + /// + public ColumnMappingCollection Columns { get; } + + /// + /// Set the access and naming strategy for this property. + /// + public AccessStrategyBuilder Access { get; } + + /// + /// Specify that this property is insertable + /// + public PropertyPart Insert() + { + attributes.Set("Insert", Layer.UserSupplied, nextBool); + nextBool = true; + + return this; + } + + /// + /// Specify that this property is updatable + /// + public PropertyPart Update() + { + attributes.Set("Update", Layer.UserSupplied, nextBool); + nextBool = true; + + return this; + } + + /// + /// Specify the column length + /// + /// Column length + public PropertyPart Length(int length) + { + columnAttributes.Set("Length", Layer.UserSupplied, length); + return this; + } + + /// + /// Specify the nullability of this property + /// + public PropertyPart Nullable() + { + columnAttributes.Set("NotNull", Layer.UserSupplied, !nextBool); + nextBool = true; + return this; + } + + /// + /// Specify that this property is read-only + /// + public PropertyPart ReadOnly() + { + attributes.Set("Insert", Layer.UserSupplied, !nextBool); + attributes.Set("Update", Layer.UserSupplied, !nextBool); + nextBool = true; + return this; + } + + /// + /// Specify the property formula + /// + /// Formula + public PropertyPart Formula(string formula) + { + attributes.Set("Formula", Layer.UserSupplied, formula); + return this; + } + + /// + /// Specify the lazy-loading behaviour + /// + public PropertyPart LazyLoad() + { + attributes.Set("Lazy", Layer.UserSupplied, nextBool); + nextBool = true; + return this; + } + + /// + /// Specify an index name + /// + /// Index name + public PropertyPart Index(string index) + { + columnAttributes.Set("Index", Layer.UserSupplied, index); + return this; + } + + /// + /// Specifies that a custom type (an implementation of ) should be used for this property for mapping it to/from one or more database columns whose format or type doesn't match this .NET property. + /// + /// A type which implements . + /// This property mapping to continue the method chain + public PropertyPart CustomType() + { + return CustomType(typeof(TCustomtype)); + } + + /// + /// Specifies that a custom type (an implementation of ) should be used for this property for mapping it to/from one or more database columns whose format or type doesn't match this .NET property. + /// + /// A type which implements . + /// This property mapping to continue the method chain + public PropertyPart CustomType(Type type) + { + if (typeof(ICompositeUserType).IsAssignableFrom(type)) + AddColumnsFromCompositeUserType(type); + + attributes.Set("Type", Layer.UserSupplied, new TypeReference(type)); + return this; + } + + /// + /// Specifies that a custom type (an implementation of ) should be used for this property for mapping it to/from one or more database columns whose format or type doesn't match this .NET property. + /// + /// A type which implements . + /// This property mapping to continue the method chain + public PropertyPart CustomType(string type) + { + attributes.Set("Type", Layer.UserSupplied, new TypeReference(type)); + + return this; + } + + /// + /// Specifies that a custom type (an implementation of ) should be used for this property for mapping it to/from one or more database columns whose format or type doesn't match this .NET property. + /// + /// A function which returns a type which implements . The argument of the function is the mapped property type + /// This property mapping to continue the method chain + public PropertyPart CustomType(Func typeFunc) + { + var type = typeFunc.Invoke(member.PropertyType); + return CustomType(type); + } + + void AddColumnsFromCompositeUserType(Type compositeUserType) + { + var inst = (ICompositeUserType)Activator.CreateInstance(compositeUserType); + + foreach (var name in inst.PropertyNames) + { + Columns.Add(name); + } + } + + /// + /// Specify a custom SQL type + /// + /// SQL type + public PropertyPart CustomSqlType(string sqlType) + { + columnAttributes.Set("SqlType", Layer.UserSupplied, sqlType); + return this; + } + + /// + /// Specify that this property has a unique constraint + /// + public PropertyPart Unique() + { + columnAttributes.Set("Unique", Layer.UserSupplied, nextBool); + nextBool = true; + return this; + } + + /// + /// Specify decimal precision + /// + /// Decimal precision + public PropertyPart Precision(int precision) + { + columnAttributes.Set("Precision", Layer.UserSupplied, precision); + return this; + } + + /// + /// Specify decimal scale + /// + /// Decimal scale + public PropertyPart Scale(int scale) + { + columnAttributes.Set("Scale", Layer.UserSupplied, scale); + return this; + } + + /// + /// Specify a default value + /// + /// Default value + public PropertyPart Default(string value) + { + columnAttributes.Set("Default", Layer.UserSupplied, value); + return this; + } + + /// + /// Specifies the name of a multi-column unique constraint. + /// + /// Name of constraint + public PropertyPart UniqueKey(string keyName) + { + columnAttributes.Set("UniqueKey", Layer.UserSupplied, keyName); + return this; + } + + /// + /// Specify that this property is optimistically locked + /// + public PropertyPart OptimisticLock() + { + attributes.Set("OptimisticLock", Layer.UserSupplied, nextBool); + nextBool = true; + return this; + } + + /// + /// Inverts the next boolean + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + public PropertyPart Not + { + get + { + nextBool = !nextBool; + return this; + } + } + + /// + /// Specify a check constraint + /// + /// Constraint name + public PropertyPart Check(string constraint) + { + columnAttributes.Set("Check", Layer.UserSupplied, constraint); + return this; + } + + PropertyMapping IPropertyMappingProvider.GetPropertyMapping() + { + var mapping = new PropertyMapping(attributes.Clone()) + { + ContainingEntityType = parentType, + Member = member + }; + + if (Columns.Count == 0 && !mapping.IsSpecified("Formula")) + { + var columnMapping = new ColumnMapping(columnAttributes.Clone()); + columnMapping.Set(x => x.Name, Layer.Defaults, member.Name); + mapping.AddColumn(Layer.Defaults, columnMapping); + } + + foreach (var column in Columns) + mapping.AddColumn(Layer.UserSupplied, column.Clone()); + + foreach (var column in mapping.Columns) + { + if (member.PropertyType.IsNullableType() && member.PropertyType.IsEnum()) + column.Set(x => x.NotNull, Layer.Defaults, false); + + column.MergeAttributes(columnAttributes); + } + + mapping.Set(x => x.Name, Layer.Defaults, mapping.Member.Name); + mapping.Set(x => x.Type, Layer.Defaults, GetDefaultType()); + + return mapping; + } + + TypeReference GetDefaultType() + { + var type = new TypeReference(member.PropertyType); + + if (member.PropertyType.IsEnum()) + type = new TypeReference(typeof(EnumStringType<>).MakeGenericType(member.PropertyType)); + + if (member.PropertyType.IsNullableType() && member.PropertyType.IsEnum()) + type = new TypeReference(typeof(EnumStringType<>).MakeGenericType(member.PropertyType.GetGenericArguments()[0])); + + return type; + } +} From 87acc653adc8bb32ce2fc16edaea85026f56779b Mon Sep 17 00:00:00 2001 From: visubesy Date: Mon, 17 Mar 2025 17:30:50 +0100 Subject: [PATCH 4/4] Fix line endings in changed files - Change the line endings in the modified files from CRLF to LF. --- .../PropertyConventionTests.cs | 574 +++++++++--------- .../Mapping/ClassMapConventionsTester.cs | 224 +++---- 2 files changed, 399 insertions(+), 399 deletions(-) diff --git a/src/FluentNHibernate.Testing/ConventionsTests/OverridingFluentInterface/PropertyConventionTests.cs b/src/FluentNHibernate.Testing/ConventionsTests/OverridingFluentInterface/PropertyConventionTests.cs index 05f7af47e..651a08b9d 100644 --- a/src/FluentNHibernate.Testing/ConventionsTests/OverridingFluentInterface/PropertyConventionTests.cs +++ b/src/FluentNHibernate.Testing/ConventionsTests/OverridingFluentInterface/PropertyConventionTests.cs @@ -1,288 +1,288 @@ -using System; -using System.Linq; -using System.Linq.Expressions; -using FluentNHibernate.Automapping.TestFixtures; -using FluentNHibernate.Automapping.TestFixtures.CustomTypes; -using FluentNHibernate.Conventions.Helpers.Builders; -using FluentNHibernate.Conventions.Instances; -using FluentNHibernate.Mapping; -using FluentNHibernate.MappingModel; -using NUnit.Framework; - -namespace FluentNHibernate.Testing.ConventionsTests.OverridingFluentInterface; - -[TestFixture] -public class PropertyConventionTests -{ - PersistenceModel model; - IMappingProvider mapping; - Type mappingType; - - [SetUp] - public void CreatePersistenceModel() - { - model = new PersistenceModel(); - } - - [Test] - public void AccessShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Access.Field()); - - Convention(x => x.Access.Property()); - - VerifyModel(x => x.Access.ShouldEqual("field")); - } - - [Test] - public void ColumnNameShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Column("xxx")); - - Convention(x => x.Column("yyy")); - - VerifyModel(x => - { - x.Columns.Count().ShouldEqual(1); - x.Columns.First().Name.ShouldEqual("xxx"); - }); - } - - [Test] - public void SqlTypeShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.CustomSqlType("sql-type")); - - Convention(x => x.CustomSqlType("type")); - - VerifyModel(x => x.Columns.First().SqlType.ShouldEqual("sql-type")); - } - - [Test] - public void TypeShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.CustomType()); - - Convention(x => x.CustomType()); - - VerifyModel(x => x.Type.GetUnderlyingSystemType().ShouldEqual(typeof(CustomUserType))); - } - - [Test] - public void FormulaShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Formula("form")); - - Convention(x => x.Formula("xxx")); - - VerifyModel(x => x.Formula.ShouldEqual("form")); - } - - [Test] - public void GeneratedShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Generated.Always()); - - Convention(x => x.Generated.Never()); - - VerifyModel(x => x.Generated.ShouldEqual("always")); - } - - [Test] - public void InsertShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Insert()); - - Convention(x => x.Not.Insert()); - - VerifyModel(x => x.Insert.ShouldBeTrue()); - } - - [Test] - public void NullableShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Nullable()); - - Convention(x => x.Not.Nullable()); - - VerifyModel(x => x.Columns.First().NotNull.ShouldBeFalse()); - } - - [Test] - public void OptimisticLockShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.OptimisticLock()); - - Convention(x => x.Not.OptimisticLock()); - - VerifyModel(x => x.OptimisticLock.ShouldBeTrue()); - } - - [Test] - public void ReadOnlyShouldntOverwriteInsert() - { - Mapping(x => x.LineOne, x => x.Insert()); - - Convention(x => x.ReadOnly()); - - VerifyModel(x => x.Insert.ShouldBeTrue()); - } - - [Test] - public void ReadOnlyShouldntOverwriteUpdate() - { - Mapping(x => x.LineOne, x => x.Update()); - - Convention(x => x.ReadOnly()); - - VerifyModel(x => x.Update.ShouldBeTrue()); - } - - [Test] - public void ReadOnlyShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.ReadOnly()); - - Convention(x => x.Not.ReadOnly()); - - VerifyModel(x => - { - x.Insert.ShouldBeFalse(); - x.Update.ShouldBeFalse(); - }); - } - - [Test] - public void UniqueShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Unique()); - - Convention(x => x.Not.Unique()); - - VerifyModel(x => x.Columns.First().Unique.ShouldBeTrue()); - } - - [Test] - public void UniqueKeyShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.UniqueKey("key")); - - Convention(x => x.UniqueKey("test")); - - VerifyModel(x => x.Columns.First().UniqueKey.ShouldEqual("key")); - } - - [Test] - public void UpdateShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Update()); - - Convention(x => x.Not.Update()); - - VerifyModel(x => x.Update.ShouldBeTrue()); - } - - [Test] - public void LengthShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Length(100)); - - Convention(x => x.Length(10)); - - VerifyModel(x => x.Columns.First().Length.ShouldEqual(100)); - } - - [Test] - public void LazyShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.LazyLoad()); - - Convention(x => x.Not.LazyLoad()); - - VerifyModel(x => x.Lazy.ShouldBeTrue()); - } - - [Test] - public void IndexShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Index("value")); - - Convention(x => x.Index("xxx")); - - VerifyModel(x => x.Columns.First().Index.ShouldEqual("value")); - } - - [Test] - public void PrecisionShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Precision(100)); - - Convention(x => x.Precision(200)); - - VerifyModel(x => x.Columns.First().Precision.ShouldEqual(100)); - } - - [Test] - public void ScaleShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Scale(100)); - - Convention(x => x.Scale(200)); - - VerifyModel(x => x.Columns.First().Scale.ShouldEqual(100)); - } - - [Test] - public void DefaultShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Default("value")); - - Convention(x => x.Default("xxx")); - - VerifyModel(x => x.Columns.First().Default.ShouldEqual("value")); - } - - [Test] - public void CheckShouldntBeOverwritten() - { - Mapping(x => x.LineOne, x => x.Check("value")); - - Convention(x => x.Check("xxx")); - - VerifyModel(x => x.Columns.First().Check.ShouldEqual("value")); - } - - #region Helpers - - void Convention(Action convention) - { - model.Conventions.Add(new PropertyConventionBuilder().Always(convention)); - } - - void Mapping(Expression> property, Action mappingDefinition) - { - var classMap = new ClassMap(); - classMap.Id(x => x.Id); - var map = classMap.Map(property); - - mappingDefinition(map); - - mapping = classMap; - mappingType = typeof(ExampleClass); - } - - void VerifyModel(Action modelVerification) - { - model.Add(mapping); - - var generatedModels = model.BuildMappings(); - var modelInstance = generatedModels - .First(x => x.Classes.FirstOrDefault(c => c.Type == mappingType) is not null) - .Classes.First() - .Properties.First(); - - modelVerification(modelInstance); - } - - #endregion +using System; +using System.Linq; +using System.Linq.Expressions; +using FluentNHibernate.Automapping.TestFixtures; +using FluentNHibernate.Automapping.TestFixtures.CustomTypes; +using FluentNHibernate.Conventions.Helpers.Builders; +using FluentNHibernate.Conventions.Instances; +using FluentNHibernate.Mapping; +using FluentNHibernate.MappingModel; +using NUnit.Framework; + +namespace FluentNHibernate.Testing.ConventionsTests.OverridingFluentInterface; + +[TestFixture] +public class PropertyConventionTests +{ + PersistenceModel model; + IMappingProvider mapping; + Type mappingType; + + [SetUp] + public void CreatePersistenceModel() + { + model = new PersistenceModel(); + } + + [Test] + public void AccessShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Access.Field()); + + Convention(x => x.Access.Property()); + + VerifyModel(x => x.Access.ShouldEqual("field")); + } + + [Test] + public void ColumnNameShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Column("xxx")); + + Convention(x => x.Column("yyy")); + + VerifyModel(x => + { + x.Columns.Count().ShouldEqual(1); + x.Columns.First().Name.ShouldEqual("xxx"); + }); + } + + [Test] + public void SqlTypeShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.CustomSqlType("sql-type")); + + Convention(x => x.CustomSqlType("type")); + + VerifyModel(x => x.Columns.First().SqlType.ShouldEqual("sql-type")); + } + + [Test] + public void TypeShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.CustomType()); + + Convention(x => x.CustomType()); + + VerifyModel(x => x.Type.GetUnderlyingSystemType().ShouldEqual(typeof(CustomUserType))); + } + + [Test] + public void FormulaShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Formula("form")); + + Convention(x => x.Formula("xxx")); + + VerifyModel(x => x.Formula.ShouldEqual("form")); + } + + [Test] + public void GeneratedShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Generated.Always()); + + Convention(x => x.Generated.Never()); + + VerifyModel(x => x.Generated.ShouldEqual("always")); + } + + [Test] + public void InsertShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Insert()); + + Convention(x => x.Not.Insert()); + + VerifyModel(x => x.Insert.ShouldBeTrue()); + } + + [Test] + public void NullableShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Nullable()); + + Convention(x => x.Not.Nullable()); + + VerifyModel(x => x.Columns.First().NotNull.ShouldBeFalse()); + } + + [Test] + public void OptimisticLockShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.OptimisticLock()); + + Convention(x => x.Not.OptimisticLock()); + + VerifyModel(x => x.OptimisticLock.ShouldBeTrue()); + } + + [Test] + public void ReadOnlyShouldntOverwriteInsert() + { + Mapping(x => x.LineOne, x => x.Insert()); + + Convention(x => x.ReadOnly()); + + VerifyModel(x => x.Insert.ShouldBeTrue()); + } + + [Test] + public void ReadOnlyShouldntOverwriteUpdate() + { + Mapping(x => x.LineOne, x => x.Update()); + + Convention(x => x.ReadOnly()); + + VerifyModel(x => x.Update.ShouldBeTrue()); + } + + [Test] + public void ReadOnlyShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.ReadOnly()); + + Convention(x => x.Not.ReadOnly()); + + VerifyModel(x => + { + x.Insert.ShouldBeFalse(); + x.Update.ShouldBeFalse(); + }); + } + + [Test] + public void UniqueShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Unique()); + + Convention(x => x.Not.Unique()); + + VerifyModel(x => x.Columns.First().Unique.ShouldBeTrue()); + } + + [Test] + public void UniqueKeyShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.UniqueKey("key")); + + Convention(x => x.UniqueKey("test")); + + VerifyModel(x => x.Columns.First().UniqueKey.ShouldEqual("key")); + } + + [Test] + public void UpdateShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Update()); + + Convention(x => x.Not.Update()); + + VerifyModel(x => x.Update.ShouldBeTrue()); + } + + [Test] + public void LengthShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Length(100)); + + Convention(x => x.Length(10)); + + VerifyModel(x => x.Columns.First().Length.ShouldEqual(100)); + } + + [Test] + public void LazyShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.LazyLoad()); + + Convention(x => x.Not.LazyLoad()); + + VerifyModel(x => x.Lazy.ShouldBeTrue()); + } + + [Test] + public void IndexShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Index("value")); + + Convention(x => x.Index("xxx")); + + VerifyModel(x => x.Columns.First().Index.ShouldEqual("value")); + } + + [Test] + public void PrecisionShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Precision(100)); + + Convention(x => x.Precision(200)); + + VerifyModel(x => x.Columns.First().Precision.ShouldEqual(100)); + } + + [Test] + public void ScaleShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Scale(100)); + + Convention(x => x.Scale(200)); + + VerifyModel(x => x.Columns.First().Scale.ShouldEqual(100)); + } + + [Test] + public void DefaultShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Default("value")); + + Convention(x => x.Default("xxx")); + + VerifyModel(x => x.Columns.First().Default.ShouldEqual("value")); + } + + [Test] + public void CheckShouldntBeOverwritten() + { + Mapping(x => x.LineOne, x => x.Check("value")); + + Convention(x => x.Check("xxx")); + + VerifyModel(x => x.Columns.First().Check.ShouldEqual("value")); + } + + #region Helpers + + void Convention(Action convention) + { + model.Conventions.Add(new PropertyConventionBuilder().Always(convention)); + } + + void Mapping(Expression> property, Action mappingDefinition) + { + var classMap = new ClassMap(); + classMap.Id(x => x.Id); + var map = classMap.Map(property); + + mappingDefinition(map); + + mapping = classMap; + mappingType = typeof(ExampleClass); + } + + void VerifyModel(Action modelVerification) + { + model.Add(mapping); + + var generatedModels = model.BuildMappings(); + var modelInstance = generatedModels + .First(x => x.Classes.FirstOrDefault(c => c.Type == mappingType) is not null) + .Classes.First() + .Properties.First(); + + modelVerification(modelInstance); + } + + #endregion } \ No newline at end of file diff --git a/src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapConventionsTester.cs b/src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapConventionsTester.cs index 8efab4ea0..d0a83efa4 100644 --- a/src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapConventionsTester.cs +++ b/src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapConventionsTester.cs @@ -1,113 +1,113 @@ -//using FluentNHibernate.Conventions.Helpers; -using FluentNHibernate.Conventions.Helpers; -using NUnit.Framework; - -namespace FluentNHibernate.Testing.DomainModel.Mapping; - -[TestFixture] -public class ClassMapConventionsTester -{ - [Test] - public void DynamicUpdateShouldntSetAttributeIfUnset() - { - new MappingTester() - .ForMapping(c => { }) - .Element("class").DoesntHaveAttribute("dynamic-update"); - } - - [Test] - public void DynamicUpdateShouldSetAttributeIfTrue() - { - new MappingTester() - .Conventions(conventions => conventions.Add(DynamicUpdate.AlwaysTrue())) - .ForMapping(c => { }) - .Element("class").HasAttribute("dynamic-update", "true"); - } - - [Test] - public void DynamicUpdateShouldSetAttributeIfFalse() - { - new MappingTester() - .Conventions(conventions => conventions.Add(DynamicUpdate.AlwaysFalse())) - .ForMapping(c => { }) - .Element("class").HasAttribute("dynamic-update", "false"); - } - - [Test] - public void DynamicUpdateShouldntOverrideDirectSetting() - { - new MappingTester() - .Conventions(conventions => conventions.Add(DynamicUpdate.AlwaysTrue())) - .ForMapping(c => c.Not.DynamicUpdate()) - .Element("class").HasAttribute("dynamic-update", "false"); - } - - [Test] - public void DynamicInsertShouldntSetAttributeIfUnset() - { - new MappingTester() - .ForMapping(c => { }) - .Element("class").DoesntHaveAttribute("dynamic-insert"); - } - - [Test] - public void DynamicInsertShouldSetAttributeIfTrue() - { - new MappingTester() - .Conventions(conventions => conventions.Add(DynamicInsert.AlwaysTrue())) - .ForMapping(c => { }) - .Element("class").HasAttribute("dynamic-insert", "true"); - } - - [Test] - public void DynamicInsertShouldSetAttributeIfFalse() - { - new MappingTester() - .Conventions(conventions => conventions.Add(DynamicInsert.AlwaysFalse())) - .ForMapping(c => { }) - .Element("class").HasAttribute("dynamic-insert", "false"); - } - - [Test] - public void DynamicInsertShouldntOverrideDirectSetting() - { - new MappingTester() - .Conventions(conventions => conventions.Add(DynamicInsert.AlwaysTrue())) - .ForMapping(c => c.Not.DynamicInsert()) - .Element("class").HasAttribute("dynamic-insert", "false"); - } - - [Test] - public void OptimisticLockShouldntSetAttributeIfNotSupplied() - { - new MappingTester() - .ForMapping(c => { }) - .Element("class").DoesntHaveAttribute("optimistic-lock"); - } - - [Test] - public void OptimisticLockShouldSetAttributeIfSupplied() - { - new MappingTester() - .Conventions(conventions => conventions.Add(OptimisticLock.Is(x => x.All()))) - .ForMapping(c => { }) - .Element("class").HasAttribute("optimistic-lock", "all"); - } - - [Test] - public void OptimisticLockShouldntOverrideDirectSetting() - { - new MappingTester() - .Conventions(conventions => conventions.Add(OptimisticLock.Is(x => x.All()))) - .ForMapping(c => c.OptimisticLock.Dirty()) - .Element("class").HasAttribute("optimistic-lock", "dirty"); - } - - [Test] - public void EnumsDontGetTypeOverriddenByConventionsIfExplicitlySet() - { - new MappingTester() - .ForMapping(m => m.Map(x => x.Color).CustomType(typeof(int))) - .Element("class/property[@name='Color']").HasAttribute("type", typeof(int).AssemblyQualifiedName); - } +//using FluentNHibernate.Conventions.Helpers; +using FluentNHibernate.Conventions.Helpers; +using NUnit.Framework; + +namespace FluentNHibernate.Testing.DomainModel.Mapping; + +[TestFixture] +public class ClassMapConventionsTester +{ + [Test] + public void DynamicUpdateShouldntSetAttributeIfUnset() + { + new MappingTester() + .ForMapping(c => { }) + .Element("class").DoesntHaveAttribute("dynamic-update"); + } + + [Test] + public void DynamicUpdateShouldSetAttributeIfTrue() + { + new MappingTester() + .Conventions(conventions => conventions.Add(DynamicUpdate.AlwaysTrue())) + .ForMapping(c => { }) + .Element("class").HasAttribute("dynamic-update", "true"); + } + + [Test] + public void DynamicUpdateShouldSetAttributeIfFalse() + { + new MappingTester() + .Conventions(conventions => conventions.Add(DynamicUpdate.AlwaysFalse())) + .ForMapping(c => { }) + .Element("class").HasAttribute("dynamic-update", "false"); + } + + [Test] + public void DynamicUpdateShouldntOverrideDirectSetting() + { + new MappingTester() + .Conventions(conventions => conventions.Add(DynamicUpdate.AlwaysTrue())) + .ForMapping(c => c.Not.DynamicUpdate()) + .Element("class").HasAttribute("dynamic-update", "false"); + } + + [Test] + public void DynamicInsertShouldntSetAttributeIfUnset() + { + new MappingTester() + .ForMapping(c => { }) + .Element("class").DoesntHaveAttribute("dynamic-insert"); + } + + [Test] + public void DynamicInsertShouldSetAttributeIfTrue() + { + new MappingTester() + .Conventions(conventions => conventions.Add(DynamicInsert.AlwaysTrue())) + .ForMapping(c => { }) + .Element("class").HasAttribute("dynamic-insert", "true"); + } + + [Test] + public void DynamicInsertShouldSetAttributeIfFalse() + { + new MappingTester() + .Conventions(conventions => conventions.Add(DynamicInsert.AlwaysFalse())) + .ForMapping(c => { }) + .Element("class").HasAttribute("dynamic-insert", "false"); + } + + [Test] + public void DynamicInsertShouldntOverrideDirectSetting() + { + new MappingTester() + .Conventions(conventions => conventions.Add(DynamicInsert.AlwaysTrue())) + .ForMapping(c => c.Not.DynamicInsert()) + .Element("class").HasAttribute("dynamic-insert", "false"); + } + + [Test] + public void OptimisticLockShouldntSetAttributeIfNotSupplied() + { + new MappingTester() + .ForMapping(c => { }) + .Element("class").DoesntHaveAttribute("optimistic-lock"); + } + + [Test] + public void OptimisticLockShouldSetAttributeIfSupplied() + { + new MappingTester() + .Conventions(conventions => conventions.Add(OptimisticLock.Is(x => x.All()))) + .ForMapping(c => { }) + .Element("class").HasAttribute("optimistic-lock", "all"); + } + + [Test] + public void OptimisticLockShouldntOverrideDirectSetting() + { + new MappingTester() + .Conventions(conventions => conventions.Add(OptimisticLock.Is(x => x.All()))) + .ForMapping(c => c.OptimisticLock.Dirty()) + .Element("class").HasAttribute("optimistic-lock", "dirty"); + } + + [Test] + public void EnumsDontGetTypeOverriddenByConventionsIfExplicitlySet() + { + new MappingTester() + .ForMapping(m => m.Map(x => x.Color).CustomType(typeof(int))) + .Element("class/property[@name='Color']").HasAttribute("type", typeof(int).AssemblyQualifiedName); + } } \ No newline at end of file