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

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


当前回答

使用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());
}

其他回答

你总是可以告诉EF在OnModelCreating函数中的Context类中使用约定来做到这一点,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // <... other configurations ...>
    // modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    // modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
    // modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

    // Configure Decimal to always have a precision of 18 and a scale of 4
    modelBuilder.Conventions.Remove<DecimalPropertyConvention>();
    modelBuilder.Conventions.Add(new DecimalPropertyConvention(18, 4));

    base.OnModelCreating(modelBuilder);
}

这只适用于Code First EF fyi,并适用于映射到db的所有十进制类型。

编辑,从。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

实体框架6 (Alpha, rc1)有一些叫做自定义约定的东西。设置十进制精度。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<decimal>().Configure(config => config.HasPrecision(18, 4));
}

参考:

http://entityframework.codeplex.com/wikipage?title=Custom%20Conventions http://weblogs.asp.net/scottgu/archive/2012/12/11/entity-framework-6-alpha2-now-available.aspx

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);
   }
}
[Column(TypeName = "decimal(18,2)")]

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