2015年1月19日 星期一

Entity Framework Code First建立Decimal,並設定大小

在Sql建立Decimal的時候,習慣性會設定大小,但是在使用Entity Framework Code First的時候卻發現2個問題:
1.沒辦法改變大小(預設是18,2),可能欄位太大或是小數位數不夠
2.沒辦法檢查傳入的資料有沒有在限制的範圍內,可能會發生輸入不符合規則

有人會使用float或double,然後配合[RangeAttribute]去限制大小,以及[RegularExpressionAttribute]來檢驗格式;這或許解決了資料驗證的問題,但是總不可能每個欄位都去下這些屬性,對資料庫欄位大小問題也一樣沒有解決。
首先先來解決資料庫decimal大小問題。
網路上找的最快的方式(Set decimal(16, 3) for a column in Code First Approach in EF4.3)
public class MyContext : DbContext
{
  public DbSet<myclass> MyClass;
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Entity<myclass>().Property(x => x.Sum).HasPrecision(5, 1);
    modelBuilder.Entity<myclass>().Property(x => x.Price).HasPrecision(3, 1);
    base.OnModelCreating(modelBuilder);
  }
}
解決了資料庫大小問題


測試下去就會發現,輸入多少都可以過,只是到資料庫會被截掉,要再加個驗證讓ModelState.IsValid可以為我們擋掉。
先建立一個DecimalAttribute繼承ValidationAttribute
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
public class DecimalAttribute : ValidationAttribute
{
  public int Precision = 18;
  public int Scale = 2;
  public DecimalAttribute(int Precision = 18, int Scale = 2)
  {
    this.Precision = Precision;
    this.Scale = Scale;
  }
  public override bool IsValid(object value)
  {
    if (value == null)
    {
      return true;
    }
    try
    {
      decimal valueAsDecimal = Convert.ToDecimal(value);
      SqlDecimal sqlDecimal = SqlDecimal.ConvertToPrecScale(new SqlDecimal(valueAsDecimal), Precision, Scale);
    }
    catch (Exception ex)
    {
      if (string.IsNullOrEmpty(base.ErrorMessage) == true)
      {
        base.ErrorMessage = ex.Message;
      }
      return false;
    }
    return true;
  }
}
傳入資料測試驗證機制正常運行

延伸閱讀:
Entity Framework Code First依屬性(Attribute)設定SQL欄位
Entity Framework Code First依屬性(Attribute)設定SQL欄位 (續)

沒有留言 :

張貼留言

Related Posts Plugin for WordPress, Blogger...