Skip to content

Settings.GenerateHasDefaultValueSql

Simon Hughes edited this page Aug 30, 2026 · 1 revision

Settings.GenerateHasDefaultValueSql

Puts each column's SQL default into the EF model with .HasDefaultValueSql(), so EF knows about it rather than just your POCO.

Type bool
Default false
Applies to EF Core only
Databases All
In Database.tt? Yes

What it does

A column default can live in two places in the generated code, and they are independent:

  • In the POCO, as a constructor assignment or property initialiser. That is Settings.IncludeColumnsWithDefaults, which is on by default.
  • In the EF model, as .HasDefaultValueSql("...") in the configuration. That is this setting, which is off by default.

The second tells EF Core the database has a default. That matters for migrations, for ValueGeneratedOnAdd inference, and for anything that reflects over the model.

Example

Product.UnitPrice is declared decimal(18, 2) NOT NULL CONSTRAINT DF_Product_UnitPrice DEFAULT ((0)).

Settings.GenerateHasDefaultValueSql = false (default)

    // Product
    public class ProductConfiguration : IEntityTypeConfiguration<Product>
    {
        public void Configure(EntityTypeBuilder<Product> builder)
        {
            builder.ToTable("Product", "dbo");
            builder.HasKey(x => x.ProductId);

            builder.Property(x => x.ProductId).HasColumnName(@"ProductId").HasColumnType("int").IsRequired().ValueGeneratedOnAdd().UseIdentityColumn();
            builder.Property(x => x.ProductName).HasColumnName(@"ProductName").HasColumnType("nvarchar(100)").IsRequired().HasMaxLength(100);
            builder.Property(x => x.UnitPrice).HasColumnName(@"UnitPrice").HasColumnType("decimal(18,2)").HasPrecision(18,2).IsRequired();
            builder.Property(x => x.Notes).HasColumnName(@"Notes").HasColumnType("nvarchar(max)").IsRequired(false);
            builder.Property(x => x.CategoryId).HasColumnName(@"CategoryId").HasColumnType("int").IsRequired();
            builder.Property(x => x.DisplayLabel).HasColumnName(@"DisplayLabel").HasColumnType("nvarchar(150)").IsRequired(false).HasMaxLength(150).ValueGeneratedOnAddOrUpdate();

            // Foreign keys
            builder.HasOne(a => a.Category).WithMany(b => b.Products).HasForeignKey(c => c.CategoryId).OnDelete(DeleteBehavior.ClientSetNull).HasConstraintName("FK_Product_Category");
        }
    }

Settings.GenerateHasDefaultValueSql = true

    // Product
    public class ProductConfiguration : IEntityTypeConfiguration<Product>
    {
        public void Configure(EntityTypeBuilder<Product> builder)
        {
            builder.ToTable("Product", "dbo");
            builder.HasKey(x => x.ProductId);

            builder.Property(x => x.ProductId).HasColumnName(@"ProductId").HasColumnType("int").IsRequired().ValueGeneratedOnAdd().UseIdentityColumn();
            builder.Property(x => x.ProductName).HasColumnName(@"ProductName").HasColumnType("nvarchar(100)").IsRequired().HasMaxLength(100);
            builder.Property(x => x.UnitPrice).HasColumnName(@"UnitPrice").HasColumnType("decimal(18,2)").HasPrecision(18,2).IsRequired().HasDefaultValueSql(@"0");
            builder.Property(x => x.Notes).HasColumnName(@"Notes").HasColumnType("nvarchar(max)").IsRequired(false);
            builder.Property(x => x.CategoryId).HasColumnName(@"CategoryId").HasColumnType("int").IsRequired();
            builder.Property(x => x.DisplayLabel).HasColumnName(@"DisplayLabel").HasColumnType("nvarchar(150)").IsRequired(false).HasMaxLength(150).ValueGeneratedOnAddOrUpdate();

            // Foreign keys
            builder.HasOne(a => a.Category).WithMany(b => b.Products).HasForeignKey(c => c.CategoryId).OnDelete(DeleteBehavior.ClientSetNull).HasConstraintName("FK_Product_Category");
        }
    }

The raw SQL default is emitted verbatim, brackets and all, exactly as the database reports it.

When to use it

You are moving to migrations. Scaffolding an initial migration from a reverse-engineered model produces an AlterColumn for every defaulted column unless the model knows the defaults are already there. Turning this on makes the initial migration empty, which is the whole objective - see Migrations.

Something reflects over the EF model to build documentation, an admin UI or a schema comparison. The defaults are only visible there if this is on.

Leave it off if the generated code is a read model over a database somebody else owns. The defaults are then not your business and the extra fluent calls are noise.

Gotchas

Sequence defaults are always emitted, regardless of this setting. A column defaulted to NEXT VALUE FOR [dbo].[MySequence] gets .HasDefaultValueSql() whether this is on or off, because EF cannot work out the value any other way. So you may see the call appear on some columns with the setting off, which looks like a bug and is not.

The SQL is copied verbatim and is dialect-specific. (getutcdate()) is SQL Server; now() is PostgreSQL. The generated model is not portable between providers, which only matters if you were hoping it would be.

Turning it on can conflict with the POCO default. With both this and IncludeColumnsWithDefaults on, the value is set in C# and declared in the model. EF then sends the C# value on insert, so the database default never fires. Harmless when they agree, confusing when they drift.

EF Core only. On EF 6 the setting is read and ignored.

Computed columns are not defaults. They are handled by Settings.UsePrivateSetterForComputedColumns and are always emitted as ValueGeneratedOnAddOrUpdate().

See also

Clone this wiki locally