Decimal precision and scale in EF Code First
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Decimal columns are one of the places where code-first defaults can cause expensive surprises. If you let Entity Framework choose the database type without thinking about precision and scale, values can be rounded, truncated, or stored with a shape that does not match the business rule.
What Precision and Scale Mean
A decimal definition such as decimal(18, 2) has two parts:
- precision is the total number of digits that can be stored
- scale is the number of digits to the right of the decimal point
So decimal(18, 2) can store values up to 9999999999999999.99, while decimal(5, 4) is better suited for rates such as 0.1250. Choosing these numbers is a domain decision, not just a database detail. Money, tax rates, discounts, and scientific measurements all need different limits.
In EF Code First, making the column shape explicit helps in three ways. It protects data integrity, keeps migrations predictable, and makes the intent clear to the next developer who reads the model.
Configuring Precision in Code First
The most portable way to set precision and scale is the Fluent API. The example below defines an Invoice entity and ensures the total and tax rate map to the right SQL types.
Total gets enough room for currency values, while TaxRate reserves more fractional detail. That split is common: monetary amounts usually need a moderate scale, but rates and ratios often need a much finer one.
If you are on a modern EF Core version, you can also use the Precision attribute for simple cases:
The Fluent API is still worth knowing because it keeps database concerns in one place and works well when different providers need different conventions.
Choosing the Right Values
There is no universal best precision and scale. The right choice depends on the largest legal value and the smallest meaningful fractional step.
A few practical examples:
- unit price: often
decimal(18, 2)ordecimal(19, 4)depending on the domain - interest rate: often
decimal(5, 4)ordecimal(9, 6) - quantity with fractions: sometimes
decimal(18, 3)ordecimal(18, 6)
The key is to model the real business limit. If you know an amount should never exceed a certain size, encode that limit deliberately. If you need more fractional precision for calculations than for display, keep the stored scale higher and round only at the presentation layer.
After changing precision or scale, generate a migration and inspect the SQL. That step is important because provider defaults differ, and a migration can reveal whether EF will alter the column exactly the way you expect.
Common Pitfalls
- Relying on provider defaults for decimal columns. Defaults are not always aligned with the business domain and can change between providers.
- Using
doubleorfloatfor money. Binary floating-point types are fast, but they are the wrong tool for exact decimal amounts. - Picking a scale that is too small. The app may appear correct until a calculation starts rounding values in production.
- Changing precision in the model without applying and reviewing the migration. The code and database can drift apart if the schema is never updated.
- Reusing one decimal definition for every field. Price, exchange rate, and quantity often need different scales.
Summary
- Precision is total digits, and scale is digits after the decimal point.
- In EF Code First, configure decimal columns explicitly so the generated schema matches the domain.
- The Fluent API with
HasPrecisionis a reliable way to define currency, rate, and measurement columns. - Use decimal types for exact numeric values such as money, not
doubleorfloat. - Review migrations after precision changes so the database stays in sync with the model.

