Лучшая аннотация данных для десятичной (18,2)
У меня есть столбец внутри моего SQL Server 2008 с типом Decimal(18,2)
. Но на основе сущности, какова лучшая проверка аннотации данных, которую я могу применить к этому свойству, внутри моего веб-приложения asp.net MVC?
Ответы
Ответ 1
Нет явной аннотации данных для десятичной дроби, поэтому вам нужно использовать два отдельных для добавления ограничений.
Две десятичные точки
[RegularExpression(@"^\d+\.\d{0,2}$")]
Это регулярное выражение будет гарантировать, что свойство имеет не более двух десятичных знаков.
Максимум 18 цифр
[Range(0, 9999999999999999.99)]
Предполагая, что вы не принимаете никаких отрицательных чисел. В противном случае замените 0
на -9999999999999999.99
.
Результат
[RegularExpression(@"^\d+\.\d{0,2}$")]
[Range(0, 9999999999999999.99)]
public decimal Property { get; set; }
Ответ 2
Я думаю, что ответ @jumpingcode можно объединить в один RegularExpressionAttribute
.
[RegularExpression(@"^(0|-?\d{0,16}(\.\d{0,2})?)$")]
public decimal Property
{
get;
set;
}
Это может использоваться для любых precision
и scale
. 16 заменяется на precision
- scale
, а 2 заменяется на scale
. Регулярное выражение должно соответствовать номерам, введенным как ###
, 0.##
, .##
, 0
и ###.##
, а также отрицательные значения.
Ответ 3
Кажется, это правильный ответ (приведенные выше ответы ограничивают допустимые числа, которые могут быть вставлены в тип данных 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")]
Ответ 4
Для другого подхода, который некоторые могут считать более читаемым, вы можете переопределить метод OnModelCreating вашего DbContext для установки точности, например:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<YourEntity>()
.Property(x => x.TheProprty)
.HasPrecision(18, 2);
}
Преимущество: строго типизированное vs пользовательское регулярное выражение
Недостаток: не вижу его в классе с помощью всего лишь сканирования
Ответ 5
Следуя примеру @Schmalls (и комментируя его преобразование в атрибут), я создал рабочий пример (использует интерполяцию строк С# 6):
public class PrecisionAndScaleAttribute : RegularExpressionAttribute
{
public PrecisionAndScaleAttribute(int precision, int scale) : base([email protected]"^(0|-?\d{{0,{precision - scale}}}(\.\d{{0,{scale}}})?)$")
{
}
}
Использование:
[PrecisionAndScale(6, 2, ErrorMessage = "Total Cost must not exceed $9999.99")]
public decimal TotalCost { get; set; }
Ответ 6
[Range(1,(double) decimal.MaxValue, ErrorMessage="value should be between{1} and {2}."]
Ответ 7
Я использую почти эксклюзивно (б/с это просто и работает)
[Range(typeof(decimal), "0", "1")]
public decimal Split { get; set; }
Затем, если мне нужно конвертировать обратно в двойной, я добавляю конверсию
(double)model.Split
Ответ 8
Если вы напишите аннотацию 'column', все будет работать нормально
[Required]
[Column(TypeName = "decimal(18, 6)")]
public decimal Foo { get; set; }