From ccbff3de88cd2296ce5f34d112f49c8f67be0306 Mon Sep 17 00:00:00 2001 From: zhoupan Date: Sun, 28 Jan 2024 11:54:19 +0800 Subject: [PATCH 1/7] Create FluentNHibernateAnnotationsExtensions.cs --- .../FluentNHibernateAnnotationsExtensions.cs | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 src/FluentNHibernate/FluentNHibernateAnnotationsExtensions.cs diff --git a/src/FluentNHibernate/FluentNHibernateAnnotationsExtensions.cs b/src/FluentNHibernate/FluentNHibernateAnnotationsExtensions.cs new file mode 100644 index 000000000..9bb742791 --- /dev/null +++ b/src/FluentNHibernate/FluentNHibernateAnnotationsExtensions.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Reflection; +using System.Text; +using FluentNHibernate.MappingModel; +using FluentNHibernate.MappingModel.Identity; +using FluentNHibernate.Utils; +using NHibernate; +using NHibernate.Hql.Ast.ANTLR.Tree; +using NHibernate.Id; + +namespace FluentNHibernate; + +public static class FluentNHibernateAnnotationsExtensions +{ + private static INHibernateLogger Log { get; set; } + + private static void UsingLog(Action log) + { + var currentLog = Log; + if (currentLog == null) + { + currentLog = NHibernateLogger.For(typeof(FluentNHibernateAnnotationsExtensions)); + if (currentLog != null) + { + Log = currentLog; + log?.Invoke(currentLog); + } + } + else + { + log?.Invoke(currentLog); + } + } + + private static void Debug(string format, params object[] args) + { + UsingLog(log => log.Debug(format, args)); + } + + /// + /// Try apply an attribute to target. + /// + /// Target type + /// Attribute type + /// Target object + /// Attribute object + /// Change the target object based on an attribute. + /// [Apply] function should return true, only when an attribute be applied or the target object be changed. + /// + /// + /// Returns false where any arguments is null, otherwise return [Apply] function's result. + /// + public static bool TryApply( + TTarget target, + TAttribute attribute, + Func apply + ) + where TAttribute : Attribute + { + if (target == null || attribute == null || apply == null) + { + return false; + } + return apply.Invoke(target, attribute); + } + + /// + /// Set ColumnMapping.NotNull when [Required] present. + /// + /// + /// + /// ColumnMapping + /// RequiredAttribute + /// + public static bool TryApply(this ColumnMapping mapping, RequiredAttribute attribute) + { + return TryApply( + mapping, + attribute, + (mapping, attribute) => + { + Debug( + "[{0}] TryApply(mapping={1}, attribute={2}) Set(NotNull=true)", + typeof(FluentNHibernateAnnotationsExtensions), + mapping, + attribute + ); + + mapping.Set(x => x.NotNull, Layer.Defaults, true); + return true; + } + ); + } + + /// + /// Set ColumnMapping.Length when [MaxLength] present. + /// + /// + /// ColumnMapping + /// MaxLengthAttribute + /// + public static bool TryApply(this ColumnMapping mapping, MaxLengthAttribute attribute) + { + return TryApply( + mapping, + attribute, + (mapping, attribute) => + { + Debug( + "[{0}] TryApply(mapping={1}, attribute={2}) Set(Length={3})", + typeof(FluentNHibernateAnnotationsExtensions), + mapping, + attribute, + attribute.Length + ); + + mapping.Set(x => x.Length, Layer.Defaults, attribute.Length); + return true; + } + ); + } + + /// + /// Configure GeneratorMapping.Class to [assinged] when [DatabaseGenerated(DatabaseGeneratedOption.None)] present. + /// Configure GeneratorMapping.Class to [identity] when [DatabaseGenerated(DatabaseGeneratedOption.Identity)] present. + /// + /// + /// + /// + /// GeneratorMapping + /// DatabaseGeneratedAttribute + /// + public static bool TryApply(this GeneratorMapping mapping, DatabaseGeneratedAttribute attribute) + { + return TryApply( + mapping, + attribute, + (mapping, attribute) => + { + var option = attribute.DatabaseGeneratedOption; + if (option == DatabaseGeneratedOption.None) + { + Debug( + "[{0}] TryApply(mapping={1}, attribute={2}) Set(Class={3})", + typeof(FluentNHibernateAnnotationsExtensions), + mapping, + attribute, + "assigned" + ); + + mapping.Set(x => x.Class, Layer.Defaults, "assigned"); + return true; + } + if (option == DatabaseGeneratedOption.Identity) + { + Debug( + "[{0}] TryApply(mapping={1}, attribute={2}) Set(Class={3})", + typeof(FluentNHibernateAnnotationsExtensions), + mapping, + attribute, + "identity" + ); + + mapping.Set(x => x.Class, Layer.Defaults, "identity"); + return true; + } + return false; + } + ); + } + + public static void TryApplyAttributesFrom( + this ColumnMapping mapping, + MemberInfo memberInfo, + bool isIdColumn + ) + { + //Prefer RequiredAttribute. + bool requiredApplied = mapping.TryApply(memberInfo.GetCustomAttribute()); + //GetType().IsNullable. + if ((!requiredApplied) && (!memberInfo.GetType().IsNullable())) + { + RequiredAttribute requiredAttribute = new RequiredAttribute(); + Debug( + "[{0}] TryApply(mapping={1}, attribute={2}) Sender=TryApplyAttributesFrom Cause=!GetType().IsNullable()", + typeof(FluentNHibernateAnnotationsExtensions), + mapping, + requiredAttribute + ); + mapping.TryApply(requiredAttribute); + } + mapping.TryApply(memberInfo.GetCustomAttribute()); + } +} From 577eba220b817e150d4a6842f96b26073b60cb23 Mon Sep 17 00:00:00 2001 From: zhoupan Date: Sun, 28 Jan 2024 12:00:01 +0800 Subject: [PATCH 2/7] Update IdentityStep.cs 1.GetDefaultGenerator: Try apply DatabaseGeneratedAttribute. 2.Map: Try apply RequiredAttribute, MaxLengthAttribute. --- src/FluentNHibernate/Automapping/Steps/IdentityStep.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/FluentNHibernate/Automapping/Steps/IdentityStep.cs b/src/FluentNHibernate/Automapping/Steps/IdentityStep.cs index e132b791c..173ebbd4c 100644 --- a/src/FluentNHibernate/Automapping/Steps/IdentityStep.cs +++ b/src/FluentNHibernate/Automapping/Steps/IdentityStep.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Reflection; using FluentNHibernate.Mapping; using FluentNHibernate.MappingModel; using FluentNHibernate.MappingModel.ClassBased; @@ -35,6 +37,8 @@ public void Map(ClassMappingBase classMap, Member member) idMapping.Member = member; idMapping.Set(x => x.Generator, Layer.Defaults, GetDefaultGenerator(member)); + columnMapping.TryApplyAttributesFrom(member.MemberInfo,isIdColumn:true); + SetDefaultAccess(member, idMapping); ((ClassMapping)classMap).Set(x => x.Id, Layer.Defaults, idMapping); @@ -67,6 +71,8 @@ GeneratorMapping GetDefaultGenerator(Member property) else defaultGenerator.Assigned(); + generatorMapping.TryApply(property.MemberInfo.GetCustomAttribute()); + return generatorMapping; } } From d6a346eaa9c1b81ccb20ec5c616f22a2d51a729f Mon Sep 17 00:00:00 2001 From: zhoupan Date: Sun, 28 Jan 2024 12:00:40 +0800 Subject: [PATCH 3/7] Update PropertyStep.cs Map: Try apply RequiredAttribute, MaxLengthAttribute. --- src/FluentNHibernate/Automapping/Steps/PropertyStep.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FluentNHibernate/Automapping/Steps/PropertyStep.cs b/src/FluentNHibernate/Automapping/Steps/PropertyStep.cs index 661811897..b96ce798b 100644 --- a/src/FluentNHibernate/Automapping/Steps/PropertyStep.cs +++ b/src/FluentNHibernate/Automapping/Steps/PropertyStep.cs @@ -89,6 +89,8 @@ private PropertyMapping GetPropertyMapping(Type type, Member property) mapping.Set(x => x.Name, Layer.Defaults, mapping.Member.Name); mapping.Set(x => x.Type, Layer.Defaults, GetDefaultType(property)); + columnMapping.TryApplyAttributesFrom(property.MemberInfo,isIdColumn:false); + SetDefaultAccess(property, mapping); return mapping; From 7f28cdc11011a40cd96b08d3242a8af68a1a316e Mon Sep 17 00:00:00 2001 From: zhoupan Date: Sun, 28 Jan 2024 12:02:22 +0800 Subject: [PATCH 4/7] Update FluentNHibernate.csproj Upgrade net6.0 --- src/FluentNHibernate/FluentNHibernate.csproj | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/FluentNHibernate/FluentNHibernate.csproj b/src/FluentNHibernate/FluentNHibernate.csproj index 019a415c2..f93ccc5ea 100644 --- a/src/FluentNHibernate/FluentNHibernate.csproj +++ b/src/FluentNHibernate/FluentNHibernate.csproj @@ -1,7 +1,6 @@  - - netstandard2.0;net461;netcoreapp2.0 + net6.0 AnyCpu Library true @@ -9,15 +8,12 @@ true ../FluentKey.snk - - FluentKey.snk - \ No newline at end of file From 73d98cf2802fcc91e2473d93cdc15be2e4208913 Mon Sep 17 00:00:00 2001 From: zhoupan Date: Sun, 28 Jan 2024 12:24:10 +0800 Subject: [PATCH 5/7] Update DefaultAutomappingConfiguration.cs IsId: return true when [Key] present on member. --- .../Automapping/DefaultAutomappingConfiguration.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/FluentNHibernate/Automapping/DefaultAutomappingConfiguration.cs b/src/FluentNHibernate/Automapping/DefaultAutomappingConfiguration.cs index c116aecbc..1e6777227 100644 --- a/src/FluentNHibernate/Automapping/DefaultAutomappingConfiguration.cs +++ b/src/FluentNHibernate/Automapping/DefaultAutomappingConfiguration.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Reflection; using System.Runtime.CompilerServices; using FluentNHibernate.Automapping.Alterations; using FluentNHibernate.Automapping.Steps; @@ -27,6 +29,10 @@ public virtual bool ShouldMap(Type type) public virtual bool IsId(Member member) { + if (member.MemberInfo.GetCustomAttribute() != null) + { + return true; + } return member.Name.Equals("id", StringComparison.InvariantCultureIgnoreCase); } From 07358e2b181fa08059424972ab5029a38fd1c48e Mon Sep 17 00:00:00 2001 From: zhoupan Date: Sun, 28 Jan 2024 13:03:51 +0800 Subject: [PATCH 6/7] Update FluentNHibernate.csproj --- src/FluentNHibernate/FluentNHibernate.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/FluentNHibernate/FluentNHibernate.csproj b/src/FluentNHibernate/FluentNHibernate.csproj index f93ccc5ea..857882004 100644 --- a/src/FluentNHibernate/FluentNHibernate.csproj +++ b/src/FluentNHibernate/FluentNHibernate.csproj @@ -1,6 +1,6 @@  - net6.0 + netstandard2.0;net461;netcoreapp2.0;net6.0 AnyCpu Library true @@ -10,6 +10,7 @@ + From 6fd48cffe154b723010fe8efc6ef598ae617f2f5 Mon Sep 17 00:00:00 2001 From: zhoupan Date: Sun, 28 Jan 2024 13:04:04 +0800 Subject: [PATCH 7/7] Update FluentNHibernateAnnotationsExtensions.cs --- src/FluentNHibernate/FluentNHibernateAnnotationsExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FluentNHibernate/FluentNHibernateAnnotationsExtensions.cs b/src/FluentNHibernate/FluentNHibernateAnnotationsExtensions.cs index 9bb742791..3b7f0825b 100644 --- a/src/FluentNHibernate/FluentNHibernateAnnotationsExtensions.cs +++ b/src/FluentNHibernate/FluentNHibernateAnnotationsExtensions.cs @@ -183,7 +183,7 @@ bool isIdColumn //GetType().IsNullable. if ((!requiredApplied) && (!memberInfo.GetType().IsNullable())) { - RequiredAttribute requiredAttribute = new RequiredAttribute(); + RequiredAttribute requiredAttribute = new (); Debug( "[{0}] TryApply(mapping={1}, attribute={2}) Sender=TryApplyAttributesFrom Cause=!GetType().IsNullable()", typeof(FluentNHibernateAnnotationsExtensions),