decimal 精度解决
continuous-integration/drone/push Build is passing Details

IRC_NewDev
hang 2024-09-17 18:53:56 +08:00
parent ab68a63bdd
commit 65e47d9918
5 changed files with 145 additions and 70 deletions

View File

@ -1,10 +1,10 @@
namespace System.ComponentModel.DataAnnotations
{
[AttributeUsage(
namespace System.ComponentModel.DataAnnotations;
[AttributeUsage(
AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,
AllowMultiple = false)]
public class GuidNotEmptyAttribute : ValidationAttribute
{
public class GuidNotEmptyAttribute : ValidationAttribute
{
public const string DefaultErrorMessage = "The {0} field must not be empty";
public GuidNotEmptyAttribute() : base(DefaultErrorMessage) { }
@ -24,10 +24,10 @@
return true;
}
}
}
}
public class NotDefaultAttribute : ValidationAttribute
{
public class NotDefaultAttribute : ValidationAttribute
{
public const string DefaultErrorMessage = "The {0} field is is not passed or not set a valid value";
public NotDefaultAttribute() : base(DefaultErrorMessage) { }
@ -49,11 +49,11 @@
// non-null ref type
return true;
}
}
}
public class CanConvertToTimeAttribute : ValidationAttribute
{
public class CanConvertToTimeAttribute : ValidationAttribute
{
public const string DefaultErrorMessage = "The {0} field is is not a valid DateTime value";
public CanConvertToTimeAttribute() : base(DefaultErrorMessage) { }
@ -73,6 +73,17 @@
return false;
}
}
}
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class DecimalPrecisionAttribute : Attribute
{
public int Precision { get; }
public int Scale { get; }
public DecimalPrecisionAttribute(int precision, int scale)
{
Precision = precision;
Scale = scale;
}
}

View File

@ -9,7 +9,9 @@ using System.Threading.Tasks;
namespace IRaCIS.Core.Infra.EFCore;
/// <summary>
/// 设置decimal 默认精度问题 但是用ef迁移工具的时候还是会提示No store type was specified for the decimal property但是迁移文件里面体现了该配置在dbcontext里写那么就会没该警告
/// </summary>
public class DecimalPrecisionConvention : IModelFinalizingConvention
{
private readonly int _precision;

View File

@ -24,6 +24,7 @@ using System.Reflection.Metadata;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.VisualBasic;
using System.ComponentModel.DataAnnotations;
namespace IRaCIS.Core.Infra.EFCore;
@ -67,7 +68,7 @@ public class IRaCISDBContext : DbContext
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
//decimal 不配置默认精度是18,2
configurationBuilder.Conventions.Add(_ => new DecimalPrecisionConvention(18,2));
//configurationBuilder.Conventions.Add(_ => new DecimalPrecisionConvention(18,2));
//针对字符串使用默认的长度配置为200如果标注了StringLength 其他长度就是标注的长度如果标注了MaxLength 那么就是nvarcharMax
configurationBuilder.Conventions.Add(_ => new DefaultStringLengthConvention(200));
}
@ -94,6 +95,35 @@ public class IRaCISDBContext : DbContext
#endregion
#region decimal 自定义精度,适配多种数据库
//foreach (var entityType in modelBuilder.Model.GetEntityTypes())
//{
// foreach (var property in entityType.GetProperties())
// {
// // 如果属性类型是 decimal 或 nullable decimal
// if (property.ClrType == typeof(decimal) || property.ClrType == typeof(decimal?))
// {
// // 获取自定义的 DecimalPrecisionAttribute
// var precisionAttr = property.PropertyInfo?.GetCustomAttributes(typeof(DecimalPrecisionAttribute), false)
// .FirstOrDefault() as DecimalPrecisionAttribute;
// if (precisionAttr != null)
// {
// property.SetPrecision(precisionAttr.Precision);
// property.SetScale(precisionAttr.Scale);
// }
// else
// {
// // 默认的精度设置
// property.SetPrecision(18);
// property.SetScale(2);
// }
// }
// }
//}
#endregion
//遍历实体模型手动配置
var typesToRegister = Assembly.GetExecutingAssembly().GetTypes().Where(q => q.GetInterface(typeof(IEntityTypeConfiguration<>).FullName) != null);
foreach (var type in typesToRegister)

View File

@ -109,11 +109,41 @@ public partial class <#= EntityType.Name #>: BaseFullAuditEntity
<#
}
}
if (property.ClrType == typeof(decimal) || property.ClrType == typeof(decimal?))
{
var typeName = property.GetColumnType()??""; // 获取数据库类型名称
// 匹配 decimal, numeric, 或者 number 格式
var match = System.Text.RegularExpressions.Regex.Match(typeName, @"(decimal|numeric|number)\((\d+),(\d+)\)", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
if (match.Success)
{
var precision = match.Groups[2].Value;
var scale = match.Groups[3].Value;
#>
[DecimalPrecision(<#= precision #>, <#= scale #>)]
<#
}
else
{
#>
[DecimalPrecision(18, 2)] // 默认值
<#
}
}
var dataAnnotations = property.GetDataAnnotations(annotationCodeGenerator)
.Where(a => !(a.Type == typeof(RequiredAttribute) && Options.UseNullableReferenceTypes && !property.ClrType.IsValueType)
&& a.Type != typeof(StringLengthAttribute)); // Åųý StringLengthAttribute
&& a.Type != typeof(StringLengthAttribute) // 排除 StringLengthAttribute
);
foreach (var dataAnnotation in dataAnnotations)
{
//过滤 [Column(TypeName = "decimal(18,1)")] 这种设置TypeName的 直接过滤&& a.Type != typeof(ColumnAttribute) 会报错,很奇怪
if(dataAnnotation.Arguments?.Count==0)
{
continue;
}
#>
<#= code.Fragment(dataAnnotation) #>
<#

View File

@ -9,6 +9,8 @@
4、微软官方针对这些不同的库生成实体的T4模板是一样的而且也提供了自定义模板的功能我们可以在官方模板的基础上进行自定义以适配属于我们项目的实体生成
1继承我们自己的审计基类
2生成的时候过滤Id 以及我们自己的审计字段
3为适配多种数据库自定义指定字符串长度默认长度不用标注特殊长度才标注
4为适配多种数据库自定义精度特性统一处理
程序包管理控制台命令行工具使用: