十进制的最佳数据注释(18,2)

Posted

技术标签:

【中文标题】十进制的最佳数据注释(18,2)【英文标题】:Best Data annotation for a Decimal(18,2) 【发布时间】:2013-11-17 15:17:06 【问题描述】:

我的 sql server 2008 中有一个列,类型为 Decimal(18,2)。但是在实体框架上,我可以在我的 asp.net MVC Web 应用程序中应用到这个属性的最佳数据注释验证是什么?

【问题讨论】:

你的意思是,将其限制为 2 位小数? 是的,这样数据库就不会出现异常了!! @jumpingcode 在下面的回答正确,你应该接受。 【参考方案1】:

小数点没有明确的数据注释,因此您需要使用两个单独的注释来添加约束。

两个小数点

[RegularExpression(@"^\d+(\.\d1,2)?$")]

这个正则表达式将确保属性最多有两位小数。

最多 18 位数字

[Range(0, 9999999999999999.99)]

假设您不接受任何负数。否则,将0 替换为-9999999999999999.99

结果

[RegularExpression(@"^\d+(\.\d1,2)?$")]
[Range(0, 9999999999999999.99)]
public decimal Property  get; set; 

【讨论】:

这个正则表达式无效尝试输入1234m12,它将通过表达式。点需要被转义,因为它被视为任何字符。 [正则表达式(@"^\d+\.\d0,2$")] 我相信您示例中的正则表达式应该是“^\d*.\d0,2$”。否则单个数字值将是不可接受的,但 OP 应该可以接受单个数字值。 @Jay 如何获得像 (0.1234) 或 (456.0009) 这样的小数? 很好的答案,但是,我发现正则表达式迫使你必须有小数位,这对于我的用例来说不是我需要的,所以使小数位可选的正则表达式是:“^ \d+(\.\d1,2)?$" 这对于输入货币等非常有用。 重要的是要注意 RegularExpressionAttribute 在将要测试的值转换为字符串时会考虑当前区域性(以便根据提供的正则表达式对其进行测试),因此如果当前区域性的小数点是逗号(可能是),那么您需要在正则表达式中考虑到它。【参考方案2】:

我认为@jumpingcode 的答案可以合并为一个RegularExpressionAttribute

[RegularExpression(@"^(0|-?\d0,16(\.\d0,2)?)$")]
public decimal Property

    get;
    set;

这可用于任何precisionscale。 16 替换为precision - scale,2 替换为scale。正则表达式应匹配输入的数字,如 ###0.##.##0###.## 以及负值。

【讨论】:

如果要经常使用,扩展 RegularExpression 属性可能是最好的选择。然后你可以有一个属性来提供精度和比例。【参考方案3】:

对于某些人可能认为更具可读性的不同方法,您可以覆盖 DbContext 的 OnModelCreating 方法来设置精度,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    

           modelBuilder.Entity<YourEntity>()
                    .Property(x => x.TheProprty)
                    .HasPrecision(18, 2);
    

优势:强类型 vs 自定义正则表达式

缺点:仅扫描无法在课堂上看到它

【讨论】:

【参考方案4】:

如果您编写“列”注释,则可以正常工作

    [Required]
    [Column(TypeName = "decimal(18, 6)")]
    public decimal Foo  get; set; 

【讨论】:

它不适用于 ASPNET MVC。我在运行迁移时收到此消息The store type 'decimal(18, 8)' could not be found in the SqlServer provider manifest 这种方法对我来说也是同样的结果。【参考方案5】:

这似乎是正确的答案(以上答案要么限制可以插入到 Decimal(18,2) 数据类型中的有效数字,要么在将它们应用于代码时导致编译错误——请自行确认):

同时使用以下两个约束:

两个小数点

[RegularExpression(@"^\d+.?\d0,2$", ErrorMessage = "Invalid Target Price; Maximum Two Decimal Points.")]

最多 18 位数字

  [Range(0, 9999999999999999.99, ErrorMessage = "Invalid Target Price; Max 18 digits")]

【讨论】:

【参考方案6】:

继@Schmalls 示例之后(并评论将其重新构建为属性),我创建了一个工作示例(使用 C# 6 字符串插值):

public class PrecisionAndScaleAttribute : RegularExpressionAttribute

    public PrecisionAndScaleAttribute(int precision, int scale) : base($@"^(0|-?\d0,precision - scale(\.\d0,scale)?)$")
    

    

用法:

[PrecisionAndScale(6, 2, ErrorMessage = "Total Cost must not exceed $9999.99")]
public decimal TotalCost  get; set; 

【讨论】:

可重用性的好主意重要提示RegularExpressionAttribute subclasses will not automatically emit client side validation attributes。为此,您需要致电DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(PrecisionAndScaleAttribute),typeof(RegularExpressionAttributeAdapter));【参考方案7】:

EF Core 6

你可以简单地使用:

[Precision(18,2)]
public decimal Property get; set; 

【讨论】:

【参考方案8】:
 [Range(1,(double) decimal.MaxValue, ErrorMessage="value should be between1 and 2."]

【讨论】:

【参考方案9】:

我使用的几乎是 excplusively(b/c 它简单且有效)

[Range(typeof(decimal), "0", "1")]
public decimal Split  get; set; 

如果我需要转换回双精度,我会添加一个转换

(double)model.Split

【讨论】:

【参考方案10】:

.net core/5/6 解决方案,适用于 2021 年

using System;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

[AttributeUsage(AttributeTargets.Property)]
public class ScalePrecisionValidationAttribute : ValidationAttribute

    private int _scale;
    private int _precision;

    public ScalePrecisionValidationAttribute(int scale, int precision)
    
        _scale = scale;
        _precision = precision;
    

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    
        if (value != null)
        
            if (!Regex.IsMatch(value.ToString(), $@"^(0|-?\d0,scale-precision(\.\d0,precision)?)$"))
            
                return new ValidationResult($"Allowed scale: _scale, precision: _precision");
            
        

        return ValidationResult.Success;
    

用作

[ScalePrecisionValidationAttribute(8, 3)]
public decimal Weight  get; set; 

您可能希望根据用例添加/修改额外的防护。 p.s.我使用了其他答案之一中的Regex 模式

【讨论】:

@GertArnold 谢谢。已编辑

以上是关于十进制的最佳数据注释(18,2)的主要内容,如果未能解决你的问题,请参考以下文章

使用数据注释将十进制值验证为小数点后 2 位?

将功能注入二进制文件的最佳方法

格式化我的十进制属性的正确数据注释是啥?

处理非十进制变量的最佳实践。 [ACM KDD 2009 杯]

Java基础语法

18.2.14 水codevs1475 m进制转十进制