设置EntityFramework中decimal类型数据精度

EF中默认的decimal数据精度为两位数,当我们数据库设置的精度大于2时,EF将只会保留到2为精度。

e.g.  2.1999将会被保存为2.20

网上找到常见的方法为重写DbContext的OnModelCreating方法:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{            
  modelBuilder.Entity<Product>().Property(x => x.Price).HasPrecision(18, 4);
}

但如果数据表多或者Decimal类型字段多的话,用OnModelCreating的方法将会变得相当冗余,而且不便管理。

我推荐使用Attribute属性标签进行设置,在Entity Model class中decimal的字段上方直接添加自定义拓展的属性标签即可。

e.g.

其中 [DecimalPrecision(18, 4)]即是我们自定义的精度Attribute

具体实现代码如下:

/// <summary>
    /// <para>自定义Decimal类型的精度属性</para>
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    public sealed class DecimalPrecisionAttribute : Attribute
    {

        #region Field
        private byte _precision = 18;
        public byte _scale = 4;
        #endregion

        #region Construct
        /// <summary>
        /// <para>自定义Decimal类型的精确度属性</para>
        /// </summary>
        /// <param name="precision">precision
        /// <para>精度(默认18)</para></param>
        /// <param name="scale">scale
        /// <para>小数位数(默认4)</para></param>
        public DecimalPrecisionAttribute(byte precision = 18, byte scale = 4)
        {
            Precision = precision;
            Scale = scale;
        } 
        #endregion
        
        #region Property
        /// <summary>
        /// 精确度(默认18)
        /// </summary>
        public byte Precision
        {
            get { return this._precision; }
            set { this._precision = value; }
        }

        /// <summary>
        /// 保留位数(默认4)
        /// </summary>
        public byte Scale
        {
            get { return this._scale; }
            set { this._scale = value; }
        } 
        #endregion
    }

    /// <summary>
    /// 用于modelBuilder全局设置自定义精度属性
    /// </summary>
    public class DecimalPrecisionAttributeConvention
        : PrimitivePropertyAttributeConfigurationConvention<DecimalPrecisionAttribute>
    {
        public override void Apply(ConventionPrimitivePropertyConfiguration configuration, DecimalPrecisionAttribute attribute)
        {
            if (attribute.Precision < 1 || attribute.Precision > 38)
            {
                throw new InvalidOperationException("Precision must be between 1 and 38.");
            }
            if (attribute.Scale > attribute.Precision)
            {
                throw new InvalidOperationException("Scale must be between 0 and the Precision value.");
            }
            configuration.HasPrecision(attribute.Precision, attribute.Scale);
        }
    }

再在DbContext重写OnModelCreating,添加自定义的DecimalPrecisionAttributeConvention即可以方便地任意添加需要精度控制的字段。

public class Project_DbContext : DbContext
    {
        public Project_DbContext() : base("DefaultConnection") { }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());
            base.OnModelCreating(modelBuilder);
        }

    }

 

posted @ 2018-04-13 12:29  kanek  阅读(905)  评论(0编辑  收藏  举报