Sydney_dev
Sydney_dev

Reputation: 1380

Validation 30000 No Type Specified for the Decimal Column

What's the best way of specifying a decimal precision without using attributes. I just need to set it in one place for all decimal's in my Data.Models. Its tedious specifying attributes for every decimal.

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

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

Upvotes: 28

Views: 27143

Answers (8)

harishr
harishr

Reputation: 18065

with ef core 6+ you can simplify it like

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    base.ConfigureConventions(configurationBuilder);

    configurationBuilder.Properties<string>()
        //.AreUnicode(false)
        //.AreFixedLength()
        .HaveMaxLength(256);
}

Upvotes: -1

vandsh
vandsh

Reputation: 1532

I realize this has been answered years ago in a few different variations, but one thing I would like to add is the ability to allow for specification on the property using the [Precision()] attribute for different precisions, with a fall-thru for all decimal properties on all entities:

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);
            }
        }
    }
}

Upvotes: 0

Amirhossein Yari
Amirhossein Yari

Reputation: 2326

Thanks to @Bigabdoul's answer. There are some situations that have been ignored.

For example if you have added special annotation for special fields this code doesn't care and override it. But I have changed code as below to don't modify that fields.

Maybe you use one of these codes for a special property:

1- Use Column(TypeName)

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

2- Use Precision

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

3- Use PropertyBuilder.HasPrecision Method

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

4- Use PropertyBuilder.HasColumnType method

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

5- Use IEntityTypeConfiguration Interface

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

And then

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

All of these situations will be ignored.

But this code care about them and check if there is no related annotation, it will add it to property.

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);
    }
}

Upvotes: 10

John
John

Reputation: 1

foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
   var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == typeof(decimal));
    foreach (var property in properties)
    {
       modelBuilder.Entity(entityType.Name).Property(property.Name).HasColumnType("decimal(18,2)");
    }
}

http://jameschambers.com/2019/06/No-Type-Was-Specified-for-the-Decimal-Column/

Upvotes: 0

vahid tajari
vahid tajari

Reputation: 1303

Add following to the OnModelCreating method in the dbcontext:

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)";   
            }
}

Upvotes: 23

SzilardD
SzilardD

Reputation: 1751

The Precision attribute can be used instead of hardcoding the decimal database type in C# code.

This:

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

Can be defined like this:

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

Tested with EF Core 6.

Upvotes: 10

Bigabdoul
Bigabdoul

Reputation: 991

For those who are struggling with the same issue on EntityFrameworkCore 6.0, this will do it:

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);
    }
}

Upvotes: 19

DOUMBIA Mamadou
DOUMBIA Mamadou

Reputation: 390

I experienced this issu using ASP.NET CORE 5. I added the folowing code to the OnModelcreating method in the DbContext.

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

    }

And all started working fine.

Upvotes: 9

Related Questions