Entity Framework
Code-first migration
Default values
Database schema
ORM

Code-first migration How to set default value for new property?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When you add a new property to an entity that already has rows in the database, the migration has to answer one practical question: what value should existing rows receive. In Entity Framework migrations, the answer is usually either a database default, a one-time backfill, or both.

The Simplest Case: Add the Column with a Default

In classic Entity Framework code-first migrations, you can set a default directly when adding the column. Example for EF6:

csharp
1public partial class AddIsActiveToProducts : DbMigration
2{
3    public override void Up()
4    {
5        AddColumn(
6            "dbo.Products",
7            "IsActive",
8            c => c.Boolean(nullable: false, defaultValue: true)
9        );
10    }
11
12    public override void Down()
13    {
14        DropColumn("dbo.Products", "IsActive");
15    }
16}

This does two things:

  • Existing rows get a value so the migration can succeed.
  • Future inserts also use that database default unless the application supplies another value.

That is usually what people want when the default should remain part of the schema.

Using a SQL Expression Instead of a Literal

Sometimes the default should be generated by the database, such as the current timestamp. In EF6 migrations you can use defaultValueSql:

csharp
1public partial class AddCreatedAt : DbMigration
2{
3    public override void Up()
4    {
5        AddColumn(
6            "dbo.Products",
7            "CreatedAt",
8            c => c.DateTime(nullable: false, defaultValueSql: "GETUTCDATE()")
9        );
10    }
11
12    public override void Down()
13    {
14        DropColumn("dbo.Products", "CreatedAt");
15    }
16}

Use this only for SQL expressions the target provider understands. GETUTCDATE() is a SQL Server example, not a cross-database default.

When You Only Want to Backfill Existing Rows

Sometimes the new property needs a value for existing rows, but you do not want a permanent database default for future inserts. In that case, add the column as nullable or with a temporary default, backfill the data, and then enforce the final shape.

Example:

csharp
1public partial class AddStatus : DbMigration
2{
3    public override void Up()
4    {
5        AddColumn("dbo.Orders", "Status", c => c.String());
6        Sql("UPDATE dbo.Orders SET Status = 'Pending' WHERE Status IS NULL");
7        AlterColumn("dbo.Orders", "Status", c => c.String(nullable: false, maxLength: 50));
8    }
9
10    public override void Down()
11    {
12        DropColumn("dbo.Orders", "Status");
13    }
14}

This pattern is often better when the initial value is data migration logic rather than a true schema default.

EF Core Version

If you are using EF Core instead of EF6, the generated migration looks different but the idea is the same:

csharp
1migrationBuilder.AddColumn<bool>(
2    name: "IsActive",
3    table: "Products",
4    nullable: false,
5    defaultValue: true);

For a database expression in EF Core:

csharp
1migrationBuilder.AddColumn<DateTime>(
2    name: "CreatedAt",
3    table: "Products",
4    nullable: false,
5    defaultValueSql: "GETUTCDATE()");

So the concept is stable even though the migration API differs.

Choosing the Right Strategy

Ask two questions before editing the migration:

  1. Should future rows still get this default automatically at the database level.
  2. Is the value really a static default, or is it a one-time backfill for old data.

If the answer to the first question is no, prefer a backfill migration over leaving a permanent default constraint behind. That keeps the schema closer to the real business rules.

Common Pitfalls

  • Adding a non-null column without a default or backfill, which causes the migration to fail on existing rows.
  • Using defaultValue when the database should calculate the value with defaultValueSql.
  • Leaving a permanent default in the schema when it was only needed for old data.
  • Assuming SQL expressions are portable across database providers.
  • Forgetting to update application code and validation rules after the schema change.

Summary

  • A new non-null property needs either a default value or a backfill strategy for existing rows.
  • Use defaultValue for a literal database default and defaultValueSql for provider-specific SQL expressions.
  • If the value is only needed for old rows, backfill with SQL and then enforce the final column shape.
  • EF6 and EF Core use different migration APIs, but the migration strategy is the same.
  • Choose the option that matches the business rule, not just the easiest migration to generate.

Course illustration
Course illustration

All Rights Reserved.