7

I have been trying to figure out how to set the decimal precision for EF7 (Beta 4) with no luck.

I was expecting to do something like:

modelBuilder.Entity<SomeClass>().Property(p => p.DecimalProperty).Precision(10, 6)

This does not appear to be available, but I was able to find the following class in the repository in GitHub:

https://github.com/aspnet/EntityFramework/blob/7.0.0-beta4/src/EntityFramework.Relational/RelationalDecimalTypeMapping.cs

There are no examples of using the RelationalTypeMapping classes or method signatures with them. Maybe this is just used as part of the mapping api for retrieving information?

Another place I might expect this to be is the following:

modelBuilder.Entity<SomeClass>().Property(p => p.DecimalProperty).ForRelational().ColumnType() 

or

modelBuilder.Entity<SomeClass>().Property(p => p.DecimalProperty).ForSqlServer().ColumnType()

These only takes a string, is this functionality just not implemented yet or am I just not looking in the correct place?

Edit: Just realized that string is probably for .ColumnType("decimal(10,6)") type of solution until this is built out further, still wouldn't mind getting some clarification though as I would prefer not to use strings for this

Edit: after clarification from bricelam I ended up creating the following extension to use for now to avoid using the string, and I appreciate the simplicity of their approach:

public static RelationalPropertyBuilder DecimalPrecision(this RelationalPropertyBuilder propertyBuilder, int precision, int scale)
    {
        return propertyBuilder.ColumnType($"decimal({precision},{scale})");
    }

Usage example:

modelBuilder.Entity<SomeClass>().Property(p => p.DecimalProperty).ForRelational().DecimalPrecision(10,6);

Edit: Making modification for RC1

I haven't tested these out yet, but I just threw together the following 2 samples of what this will probably look like with RC1

    public static PropertyBuilder DecimalPrecision(this PropertyBuilder propertyBuilder, string precision, string scale)
    {
        return propertyBuilder.HasColumnType($"decimal({precision},{scale})");
    }

    public static PropertyBuilder SqlDecimalPrecision(this PropertyBuilder propertyBuilder, string precision, string scale)
    {
        return propertyBuilder.ForSqlServerHasColumnType($"decimal({precision},{scale})");
    }

Since I have not yet tried this I am not sure which would be the correct usage between "HasColumnType" or "ForSqlServerHasColumnType", but hopefully this will point someone in the right direction.

Matt Sanders
  • 953
  • 1
  • 13
  • 23
  • Since all my decimal properties have the same precision, any way on implementing this on all of them in one line? I was using this with EF6: `modelBuilder.Properties().Configure(x => x.HasPrecision(18, 6));` – GregoryHouseMD Nov 19 '15 at 16:09
  • @reala valoro, I have updated the details to reflect RC1 changes – Matt Sanders Dec 15 '15 at 21:59

2 Answers2

4

Your workaround is the design we intended. Instead of having a bunch of "facets" you can set on a type like precision, scale, max length, unicode/ansi, fixed/variable length, etc. We decided to keep it simple: If the default type mapping isn't what you want, tell us what type to use. There have been talks of going back on this decision and reintroducing the "facets". If you feel strongly about it, I would encourage you to create a new issue.

Also note that there are a bunch of other bugs in type mapping right now, but they should be fixed by the time we release beta5.

bricelam
  • 28,825
  • 9
  • 92
  • 117
  • Thank you for the clarification, I edited the question with a simple extension I created to avoid the string. I wouldn't be surprised at all the see these reintroduced down the road, but I wouldn't think this warrants an issue being created as you guys have much bigger fish to fry :) I appreciate all of the work you guys are doing and am really looking forward to using EF7 more! – Matt Sanders May 22 '15 at 19:49
1

The example shown seems to be outdated as per EF RC1.

Here is how I set precision on a decimal field.

Say I have an entity

public class Review
{
    public int ReviewId { get; set; }
    public decimal TotalScore { get; set; } //I want a precision field in DB
    public DateTime CreatedOn { get; set; }
    [Timestamp]
    public byte[] RowVersion { get; set; }
}

then in my context class, on model creating, I instantiate the mapping (I could do the mapping there, but I like to keep it separated)

public class MyDbContext : DbContext
{
    public MyDbContext(DbContextOptions<MyDbContext> options ) : base(options)
    {
    }

    public DbSet<Review> Reviews { get; set; }
    //etc.

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        //Mappings
        new ReviewMap(modelBuilder.Entity<Review>());
        //etc..
    }
}

and then the mapping. Remember to use the namespace where the Model extensions are:

using Microsoft.Data.Entity; //here is where the extensions are
public class ReviewMap
{
    public ReviewMap(EntityTypeBuilder<Review> entityBuilder)
    {
        entityBuilder.HasKey(r => r.ReviewId);

        //Using the column type extension
        entityBuilder.Property(r => r.TotalScore)
            .HasColumnType($"decimal(5,2)")
            .IsRequired(true);

        //and this has nothing to do with the example but it's interesting
        //to show how to use Sql command to automatically fulfil a value 
        //when adding a new Entity
        entityBuilder.Property(r => r.CreatedOn)
            .ValueGeneratedOnAdd()
            .HasDefaultValueSql("GETUTCDATE()")
            .IsRequired(true);
    }
}
diegosasw
  • 13,734
  • 16
  • 95
  • 159