EF中对decimal类型在实体属性中的精度控制

在使用EF处理decimal类型时,默认会截断为2位小数,对于需要高精度的场景,需自定义改造。创建DecimalPrecisionAttribute类并加入到数据库上下文的模型构建器中,以实现自定义精度控制。

EF中对decimal类型在实体属性中的精度控制

EF中对decimal类型数据进行存储时,对多位小数默认会截断取2位保存,但一些高精度场合不能满足要求,则需要我们对其改造一下:
1、新建DecimalPrecisionAttribute.cs,最好和上下文在同一个命名空间内,以减少引用


```csharp
using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration.Configuration;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Web;

namespace AppBoxMvc.Models
{
    /// <summary>
    /// 精度属性控制
    /// </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);
         }

    }
}
2、OnModelCreating新增属性

```csharp
protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();//移除复数表名的契约
            modelBuilder.Conventions.Remove<IncludeMetadataConvention>();//防止黑幕交易 要不然每次都要访问
            modelBuilder.HasDefaultSchema("SCM");
            //base.OnModelCreating(modelBuilder);
            //注册函数
            modelBuilder.Conventions.Add(new FunctionsConvention("SCM", this.GetType()));
            modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());
}

注意,在NFineFramework架构中数据库方法中可能调用某个上下文,如JobAppDbContext : DbContext,则只需要在该文属性中增加一个注册即可:
modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());//注册Decimal精度函数


```csharp
    public class JobAppDbContext : DbContext
    {
        public JobAppDbContext()
            : base("JobAppDbContext")
        {
            this.Configuration.AutoDetectChangesEnabled = false;
            this.Configuration.ValidateOnSaveEnabled = false;
            this.Configuration.LazyLoadingEnabled = false;
            this.Configuration.ProxyCreationEnabled = false;
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            string assembleFileName = Assembly.GetExecutingAssembly().CodeBase.Replace("JobApp.Data.DLL", "JobApp.Mapping.DLL").Replace("file:///", "");
            Assembly asm = Assembly.LoadFile(assembleFileName);
            var typesToRegister = asm.GetTypes()
            .Where(type => !String.IsNullOrEmpty(type.Namespace))
            .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
            foreach (var type in typesToRegister)
            {
                dynamic configurationInstance = Activator.CreateInstance(type);
                modelBuilder.Configurations.Add(configurationInstance);
                modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());//注册Decimal精度函数
            }
            base.OnModelCreating(modelBuilder);
        }
    }



3、实体属性绑定

```csharp
.....
 		[DecimalPrecision(19, 4)]
        public decimal T_SCM_QUTV_BASIC_PRICE { get; set; }//购买价格

        [Display(Name = "税后价格")]
        [DecimalPrecision(19, 4)]
        public decimal T_SCM_QUTV_END_PRICE { get; set; }//税后价格
........

参考博文:https://www.cnblogs.com/su1643/p/10982197.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值