我的 sql server 2008 中有一个列,类型为Decimal(18,2)
. 但是在实体框架上,我可以在我的 asp.net MVC Web 应用程序中应用到这个属性的最佳数据注释验证是什么?
10 回答
小数没有明确的数据注释,因此您需要使用两个单独的注释来添加约束。
两个小数点
[RegularExpression(@"^\d+(\.\d{1,2})?$")]
此正则表达式将确保该属性最多有两位小数。
最多 18 位
[Range(0, 9999999999999999.99)]
假设您不接受任何负数。否则,替换0
为-9999999999999999.99
。
结果
[RegularExpression(@"^\d+(\.\d{1,2})?$")]
[Range(0, 9999999999999999.99)]
public decimal Property { get; set; }
我认为@jumpingcode 的答案可以合并为一个RegularExpressionAttribute
。
[RegularExpression(@"^(0|-?\d{0,16}(\.\d{0,2})?)$")]
public decimal Property
{
get;
set;
}
这可用于任何precision
和scale
。16 被替换为precision
-scale
并且 2 被替换为scale
。正则表达式应匹配输入的数字,如###
、0.##
、.##
、0
和###.##
以及负值。
对于某些人可能认为更具可读性的不同方法,您可以覆盖 DbContext 的 OnModelCreating 方法以设置精度,如下所示:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<YourEntity>()
.Property(x => x.TheProprty)
.HasPrecision(18, 2);
}
优点:强类型 vs 自定义正则表达式
缺点:仅扫描无法在课堂上看到它
如果您编写“列”注释,则可以正常工作
[Required]
[Column(TypeName = "decimal(18, 6)")]
public decimal Foo { get; set; }
继@Schmalls 示例(并评论将其重新构建为属性)之后,我创建了一个工作示例(使用 C# 6 字符串插值):
public class PrecisionAndScaleAttribute : RegularExpressionAttribute
{
public PrecisionAndScaleAttribute(int precision, int scale) : base($@"^(0|-?\d{{0,{precision - scale}}}(\.\d{{0,{scale}}})?)$")
{
}
}
用法:
[PrecisionAndScale(6, 2, ErrorMessage = "Total Cost must not exceed $9999.99")]
public decimal TotalCost { get; set; }
这似乎是正确的答案(上面的答案要么限制可以插入到 Decimal(18,2) 数据类型中的有效数字,要么在将它们应用于代码时导致编译错误——请自行确认):
一起使用以下两个约束:
两个小数点
[RegularExpression(@"^\d+.?\d{0,2}$", ErrorMessage = "Invalid Target Price; Maximum Two Decimal Points.")]
最多 18 位
[Range(0, 9999999999999999.99, ErrorMessage = "Invalid Target Price; Max 18 digits")]
我使用的几乎是 excplusively(b/c 它很简单而且有效)
[Range(typeof(decimal), "0", "1")]
public decimal Split { get; set; }
然后,如果我需要转换回双倍,我会添加一个转换
(double)model.Split
[Range(1,(double) decimal.MaxValue, ErrorMessage="value should be between{1} and {2}."]
在EF Core 6中
您可以简单地使用:
[Precision(18,2)]
public decimal Property{ get; set; }
.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|-?\d{{0,{scale-precision}}}(\.\d{{0,{precision}}})?)$"))
{
return new ValidationResult($"Allowed scale: {_scale}, precision: {_precision}");
}
}
return ValidationResult.Success;
}
}
用于
[ScalePrecisionValidationAttribute(8, 3)]
public decimal Weight { get; set; }
您可能需要根据用例添加/修改额外的防护。ps我使用Regex
了其他答案之一的模式