Course contentsShow
← C#
Lesson 1089 of 1,90810. Entity Framework Core ModelingFree lesson

Schema Evolution Patterns

Manage breaking database changes while supporting legacy application versions.

In this lesson, you will learn how to evolve your database schema without breaking older versions of your application that rely on the existing structure.

When you deploy a new version of an application, you often need to change the database schema. However, in environments with rolling deployments, the database might need to support both the "old" and "new" application versions simultaneously for a short period. This requires Schema Evolution Patterns, where we prioritize backward compatibility.

The "Expand and Contract" Pattern

The most reliable strategy is the Expand and Contract pattern. Instead of performing a destructive change (like renaming a column), you transition through three distinct phases:

  1. Expand: Add the new schema element (e.g., a new column) while keeping the old one. The application is updated to write to both columns or prioritize the new one, but the old code still functions.
  2. Migrate: Run a background process or a one-time script to copy data from the old column to the new column.
  3. Contract: Once all instances of the application are updated to the latest version, perform a final cleanup to remove the old column.

Implementation Illustration

If you need to rename a property User.FullName to User.DisplayName, don’t perform a RENAME command. Instead, add the new column to your entity:

public class User 
{
    // Phase 1: Keep both for compatibility
    public string FullName { get; set; } // Old
    public string DisplayName { get; set; } // New
}

By keeping FullName in the model, your legacy application instances can still function correctly. You can use SaveChanges interception or a simple property setter to ensure data parity during the transition period. Once your telemetry confirms that no traffic is hitting the old version, you update the model to remove FullName and execute the migration to drop the column.

This approach prevents downtime and "database-first" errors that occur when new code expects a schema that older nodes haven't synchronized with yet. By avoiding instant destructive changes, you ensure a graceful transition in distributed systems.

Key Takeaway: Never perform destructive schema changes immediately; use the "Expand and Contract" pattern to maintain application stability during deployments.