What are the default precision and scale for floating point types in EF core 6?

Viewed 1106

I am receiving the following warning:

No store type was specified for the decimal property 'PurchasePrice' on entity type 'ProductStatisticsKeylessEntity'. This will cause values to be silently truncated if they do not fit in the default precision and scale. Explicitly specify the SQL server column type that can accommodate all the values in 'OnModelCreating' using 'HasColumnType', specify precision and scale using 'HasPrecision', or configure a value converter using 'HasConversion'.

(emphasis mine)

I know how to set a precision and scale, but I want to know the EF default values - what exactly are the default precision and scale for decimal, float or double?

Perhaps the default values are good enough and i can set the precision/scale to the same values to hide the errors.

2 Answers

I'm not aware of any official documentation on default precision and scale mappings of C# decimal to SQL Server decimal. The quickest way is just to try.

The source code (see the initialization of the _clrTypeMappings field) reveals that decimals are mapped by default to decimal(18,2), as they have always been in Entity Framework.

Both float and double only have precision (and exponent, but no scale), so the question doesn't really apply here. But for these types it matters to which SQL Serer types they are mapped, because the definitions on both sides differ confusingly.

If we let EF generate a table from this class...

public class Num
{
    public int Id { get; set; }
    public decimal Dec { get; set; }
    public float Float { get; set; }
    public double Double { get; set; }
}

... we get this:

CREATE TABLE [dbo].[Nums](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Dec] [decimal](18, 2) NOT NULL,
    [Float] [real] NOT NULL,
    [Double] [float] NOT NULL,
 CONSTRAINT [PK_Nums] PRIMARY KEY CLUSTERED ([Id]))

So the default mappings from CLR to SQL Server types are:

  • decimal to decimal(18,2)
  • float to real
  • double to float

Note that for float (CLR) this isn't really a default, it is the only mapping that makes sense. For double it is a default because the precision of double can be cut down by mapping instructions like:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Num>().Property(e => e.Double).HasPrecision(24);
}

In this case the Double property will mapped to a real in SQL Server because it has the storage size of a real.

Related