In this lesson, you will learn how to bypass the standard static OnModelCreating approach to generate database schemas at runtime based on external metadata or configuration files.
The Concept
Normally, EF Core models are defined at compile time using C# classes and attributes or the Fluent API. However, in scenarios like multi-tenant systems where each client might require a different set of dynamic fields, or systems that load schema definitions from JSON/XML files, you need a way to define your model structure on the fly.
To achieve this, we override the OnModelCreating method and use the ModelBuilder to programmatically inject entity types, properties, and relationships.
Implementation
Instead of relying on DbSet<T> properties, you define your model dynamically. Here is a simplified example of adding an entity type and a property to the model at runtime:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Define an entity type dynamically
var entityBuilder = modelBuilder.SharedTypeEntity<Dictionary<string, object>>("DynamicProduct");
// Add properties based on external metadata
entityBuilder.IndexerProperty<int>("Id");
entityBuilder.IndexerProperty<string>("ProductName");
// Set keys
entityBuilder.HasKey("Id");
}
By using SharedTypeEntity (often referred to as "Shadow Entities"), you can represent data as a dictionary of values. The ModelBuilder treats this dictionary exactly like a strongly-typed entity class, allowing you to map columns and define constraints based on runtime inputs rather than static code.
Why use this?
This pattern is incredibly powerful when you don't know the full structure of your database when you compile your application. By decoupling the model definition from the C# class definition, you can build flexible, data-driven applications that adapt their underlying database schema based on user-provided metadata or configuration sources without requiring a recompile.
Key Takeaway: Dynamic Model Building allows you to define your database schema programmatically at runtime using the ModelBuilder API, enabling flexible applications that can adapt to evolving data structures without static class definitions.