验证 30000 - 十进制列未指定类型

24

如何在不使用属性的情况下指定小数精度是最好的方法。 我只需要在我的Data.Models中为所有小数设置一次即可。每次都指定属性很麻烦。

public class Customer
{
    public int customerId { get; set; }

    [Column(TypeName = "decimal(18,2)")]
    public decimal AvailableAmount { get; set; }
}
7个回答

19
将以下内容添加到 dbcontext 中的 OnModelCreating 方法中:
protected override void OnModelCreating(ModelBuilder builder)
{         
   foreach (var property in builder.Model.GetEntityTypes()
                .SelectMany(t => t.GetProperties())
                .Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
            {   
              property.Relational().ColumnType = "decimal(18,2)";   
            }
}

4
“Relational()” 是从哪里来的? - Stuart Dobson
2
你应该安装 Microsoft.EntityFrameworkCore.Relational 包。 - vahid tajari
1
如果您的任何十进制列不是decimal(18,2),那么此答案是错误的。请谨慎操作... - Michail Papadakis

13

对于在 EntityFrameworkCore 6.0 上遇到同样问题的人,可以尝试如下解决方案:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    var decimalProps = modelBuilder.Model
    .GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => (System.Nullable.GetUnderlyingType(p.ClrType) ?? p.ClrType) == typeof(decimal));

    foreach (var property in decimalProps)
    {
        property.SetPrecision(18);
        property.SetScale(2);
    }
}

您还可以使用 property.SetColumnType()。 - Roman Gudkov

9

我在使用ASP.NET Core 5时遇到了这个问题。我将以下代码添加到DbContext中的OnModelCreating方法中。

protected override void OnModelCreating(ModelBuilder modelBuilder)// Crée la migration
    {
        modelBuilder.Entity<MyEntity>().Property(p => p.Prix).HasColumnType("decimal(18,4)");

    }

一切都开始正常工作了。


9
Precision 属性可用于在 C# 代码中替代硬编码十进制数据库类型。

以下是示例:

[Column(TypeName = "decimal(18,2)")]
public decimal Quantity { get; set; }

可以这样定义:

[Precision(18, 2)]
public decimal Quantity { get; set; }

使用 EF Core 6 进行测试。


看到每个小数都要指定属性真是太繁琐了。再加一个属性也没有什么区别。 - Gert Arnold

1
感谢@Bigabdoul的回答。有一些情况被忽略了。
例如,如果您为特定字段添加了特殊注释,则此代码不会关心并覆盖它。 但是,我已将代码更改为不修改那些字段。
也许您使用其中一个代码来处理特殊属性:
1- 使用Column(TypeName)
[Column(TypeName = "decimal(18,2)")]
public decimal Quantity { get; set; }

2- 使用精度

[Precision(18, 2)]
public decimal Quantity { get; set; }

3- 使用PropertyBuilder.HasPrecision 方法

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>().Property(p => p.MyProperty).HasPrecision(18, 2);
}

4- 使用 PropertyBuilder.HasColumnType 方法

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>().Property(p => p.MyProperty).HasColumnType("decimal(18,2)");
}

5- 使用IEntityTypeConfiguration 接口

public class MyEntityConfiguration : IEntityTypeConfiguration<MyEntity>
{
    public void Configure(EntityTypeBuilder<MyEntity> builder)
    {
        builder.ToTable("MyEntity");
        builder.Property(x => x.MyEntity).HasPrecision(18, 2);
    }
}

然后

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfigurationsFromAssembly(GetType().Assembly);
    // Or use explicitly
    //modelBuilder.ApplyConfiguration(new MyEntityConfiguration());
}

所有这些情况都将被忽略。

但是这段代码会关注它们并检查是否没有相关的注释,如果没有,它将添加到属性中。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    var decimalProps = modelBuilder.Model
        .GetEntityTypes()
        .SelectMany(t => t.GetProperties())
        .Where(p => (System.Nullable.GetUnderlyingType(p.ClrType) ?? p.ClrType) == typeof(decimal));

    foreach (var property in decimalProps)
    {
        var annotations = property.GetAnnotations();
        if (annotations.Count(x => x.Name is "Relational:ColumnType" or "Precision" or "Scale") != 0) continue;
        // Or Use this line if you use older version of C#
        // if (annotations.Count(x => x.Name == "Relational:ColumnType" || x.Name == "Precision" || x.Name == "Scale") != 0) continue;
        property.SetPrecision(18);
        property.SetScale(2);
    }
}

0

1
目前你的回答不够清晰。请编辑并添加更多细节,以帮助其他人理解它如何回答所提出的问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

0
我知道这个问题几年前已经有了一些不同的回答,但我想补充的一点是,希望能够使用[Precision()]属性来指定属性的不同精度,并且对所有实体上的decimal属性都生效。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // Fetch all entity classes that derive from the `BaseEntity`
    var entities = typeof(BaseEntity).Assembly.GetTypes()
        .Where(t => t.IsSubclassOf(typeof(BaseEntity)) && !t.IsAbstract);
    foreach (var entity in entities)
    {
        // Iterate thru the properties of the entity
        foreach (var property in entity.GetProperties())
        {
            // If decimal or nullable decimal 
            // and not using the `Precision` attribtue, define the precision
            if ((property.PropertyType == typeof(decimal) 
                    || property.PropertyType == typeof(decimal?)) 
                    && !property.GetCustomAttributes<PrecisionAttribute>().Any())
            {
                modelBuilder.Entity(entity)
                .Property(property.PropertyType, property.Name).HasPrecision(18, 2);
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接