我正在试验这种代码优先的方法,但我现在发现类型System的属性。Decimal被映射到Decimal(18,0)类型的sql列。

如何设置数据库列的精度?


当前回答

Dave Van den Eynde给出的答案现在已经过时了。有2个重要的变化,从EF 4.1开始,ModelBuilder类现在是DbModelBuilder,现在有一个DecimalPropertyConfiguration。HasPrecision方法,其签名为:

public DecimalPropertyConfiguration HasPrecision(
byte precision,
byte scale )

其中精度是db将存储的数字总数,而不管小数点落在哪里,scale是它将存储的小数位数。

因此,不需要像所示那样遍历属性,只需要从属性调用即可

public class EFDbContext : DbContext
{
   protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
   {
       modelBuilder.Entity<Class>().Property(object => object.property).HasPrecision(12, 10);

       base.OnModelCreating(modelBuilder);
   }
}

其他回答

这就是我正在寻找的,适用于普通的MVC项目(没有。net核心)

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<YOUR_CLASS_NAME>().Property(x => x.YOUR_DECIAML_PROP).HasPrecision(18, 6);

        base.OnModelCreating(modelBuilder);

    }
}

包管理器控制台

add-migration changeDecimalPrecision

生成的迁移

    public override void Up()
    {
        AlterColumn("dbo.YOUR_CLASS_NAME", "YOUR_DECIAML_PROP", c => c.Decimal(nullable: false, precision: 18, scale: 6));
    }

编辑,从。net 6开始,这可以用precision属性代替

(精密(精度、规模))

EF Core之前的版本:

[列(TypeName = "十进制(精度,比例)")]

定义:

精度=使用的字符总数

刻度=点后的总数。(容易混淆)

例子:

using System.ComponentModel.DataAnnotations; //.Net Core
using Microsoft.EntityFrameworkCore; //.NET 6+

public class Blog
{
    public int BlogId { get; set; }
    [Column(TypeName = "varchar(200)")]
    public string Url { get; set; }
    [Column(TypeName = "decimal(5, 2)")]
    public decimal Rating { get; set; }
    [Precision(28, 8)]
    public decimal RatingV6 { get; set; }
}

更多详情请访问:https://learn.microsoft.com/en-us/ef/core/modeling/relational/data-types

下面的代码行可以更简单地实现相同的目的:

 public class ProductConfiguration : EntityTypeConfiguration<Product>
    {
        public ProductConfiguration()
        {
            this.Property(m => m.Price).HasPrecision(10, 2);
        }
    }
[Column(TypeName = "decimal(18,2)")]

这将与EF Core代码首次迁移一起工作,如下所述。

使用KinSlayerUY的DecimalPrecisonAttribute,在EF6中,你可以创建一个惯例,它将处理具有该属性的单个属性(而不是像这个答案中那样设置DecimalPropertyConvention,这会影响所有的十进制属性)。

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public sealed class DecimalPrecisionAttribute : Attribute
{
    public DecimalPrecisionAttribute(byte precision, byte scale)
    {
        Precision = precision;
        Scale = scale;
    }
    public byte Precision { get; set; }
    public byte Scale { get; set; }
}

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中:

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