Search code examples
c#entity-framework-6dbmigrator

Entity Framework/dbMigration - Unwanted decimal rounding


I'm working on a new Code-First Entity Framework (using dbMigration) solution, and I've run into a bit of a snag that I've been unable to get past.

Even though I modified the generated Migration file to set the precision/scale for a decimal field to 18 and 9, when I run the update-database to build the database and call a method I wrote to seed the data, it's rounding the data to 2 decimal places rather than the 9 I expected. In the example data I'm trying to seed, I'm trying to set the Price property to 0.4277 but it's showing up in the database as 0.420000000

I've been looking all over for solutions to this problem, including creating an override (in my context class) for OnModelCreating, to force the precision/scale there. But when I have that in place (see the commented out line in the code below), while the database migration still works exactly as planned (including creating a DECIMAL(18,9) as expected), now the Seed call doesn't run.

I'm hoping I'm just missing something small (and easy to fix). But can anyone offer suggestions what I can try?

Below is the relevant code (including the initially-generated migration code):

public class Product
{
    public int ID { get; set; }
    public decimal Price { get; set; }
}

internal sealed class Configuration : DbMigrationsConfiguration<ConfiguratorContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(ConfiguratorContext context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data.
        SeedData.Initialize();        
    }
}

public partial class Initial : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.Products",
            c => new
            {
                ID = c.Int(nullable: false, identity: true),
                Price = c.Decimal(nullable: false, precision: 18, scale: 9)
                })
            .PrimaryKey(t => t.ID);
    }   

    public override void Down()
    {
        DropTable("dbo.Products");
    }       
}   

public class ConfiguratorContext : DbContext
{
    public ConfiguratorContext() : base("name=ConfiguratorConnectionString")
    {
        Database.SetInitializer<ConfiguratorContext>(new CreateDatabaseIfNotExists<ConfiguratorContext>());
    }

    public DbSet<Product> Products { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //modelBuilder.Entity<Product>().Property(a => a.Price).HasPrecision(18, 9);
    }
}

public class SeedData
{
    public static void Initialize()
    {
        using (var context = new ConfiguratorContext())
        {
            if (context.Products.Any())
            {
                return;   // DB has been seeded
            }

            context.Products.Add(new Product
            {
                Price = Convert.ToDecimal(0.4277),
            });

            context.SaveChanges();
        }
    }
}   

What am I missing?

Thanks!


Solution

  • I think your migration is not executing and database is created with decimal(18, 2) by default.

    You can try to use the following initializer, but it does not created database for your

    Database.SetInitializer<ConfiguratorContext>(new MigrateDatabaseToLatestVersion<ConfiguratorContext, Configuration>());
    

    The line you have commented modelBuilder.Entity<Product>().Property(a => a.Price).HasPrecision(18, 9); does the job just right.

    I would advice to move away from automatic migrations if you can, and update databases through Update-Database to have consistent and predictable results on database schema changes.