-
Notifications
You must be signed in to change notification settings - Fork 226
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 |
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.
Product.UnitPrice is declared decimal(18, 2) NOT NULL CONSTRAINT DF_Product_UnitPrice DEFAULT ((0)).
// 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");
}
} // 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.
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.
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().
- Settings.IncludeColumnsWithDefaults - the same default, in the POCO
- Migrations - the main reason to turn this on
- Settings.HiLoSequences - the sequence case
- Settings Reference
- Settings A-Z - every setting, with a page each
- Common Settings Types Explained
- Settings Callbacks
- Settings runtime values and helpers
- Filtering
- Full Control Over the Generated Code
- Enum Generation from Table Data
- Owned Entities
- JSON column support
- Global Query Filters
- Extended Property Names Feature
- Partial Properties
- File-Scoped Namespaces
- Data Annotations
- Spatial Types
- HierarchyId
- RowVersion and TimeStamp columns
- Lazy Loading
- Stored proc result sets
- Custom File-Based Templates
- Extra entities via partial classes
- INotifyPropertyChanged
- Syntax colour for T4