VOOZH about

URL: https://deepwiki.com/npgsql/efcore.pg/5.2-scaffolding-and-reverse-engineering

⇱ Scaffolding and Reverse Engineering | npgsql/efcore.pg | DeepWiki


Loading...
Menu

Scaffolding and Reverse Engineering

This page documents how the Npgsql EF Core provider reverse-engineers existing PostgreSQL databases into Entity Framework Core models. This process, known as scaffolding or database-first development, reads the database schema from PostgreSQL system catalogs and generates corresponding C# entity classes and DbContext configuration code.

For information about forward engineering (creating/modifying databases from EF Core models), see Migrations and Schema Management. For database creation and connection setup, see Database Creation and Connection Management.

Overview

Reverse engineering in the Npgsql provider is a two-phase process:


Phase 1 queries the PostgreSQL database using system catalogs to build a DatabaseModel containing all schema information. Phase 2 uses this model to generate C# code with appropriate type mappings and PostgreSQL-specific annotations.

Sources: src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs18-158

NpgsqlDatabaseModelFactory

The NpgsqlDatabaseModelFactory class is the entry point for reverse engineering. It implements EF Core's DatabaseModelFactory base class and is responsible for reading PostgreSQL schemas.

Main Entry Points


The factory provides two overloads at src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs51-58 and src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs61-158 that accept either a connection string or an existing DbConnection.

Scaffolding Pipeline

The Create method orchestrates the entire scaffolding process:

StepMethodPurpose
1PopulateGlobalDatabaseInfo()Reads database-level collation from pg_database src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs164-182
2GetEnums()Loads PostgreSQL enum types for filtering src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs1136-1174
3GetTables()Scaffolds tables, views, and materialized views from pg_class src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs187-265
4GetColumns()Scaffolds columns with PostgreSQL-specific features src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs270-508
5GetConstraints()Scaffolds primary keys, foreign keys, unique constraints from pg_constraint src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs814-1033
6GetIndexes()Scaffolds indexes with method, operators, and options from pg_index src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs548-812
7GetSequences()Scaffolds standalone sequences from pg_sequence src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs1035-1134
8GetExtensions()Scaffolds installed PostgreSQL extensions src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs1176-1192
9GetCollations()Scaffolds user-defined collations from pg_collation src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs1194-1258

Sources: src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs66-158

Querying PostgreSQL System Catalogs

The factory queries PostgreSQL's system catalogs extensively to retrieve schema information.

Key System Catalogs Used


Table and View Detection

The GetTables() method queries pg_class with a filter on relkind to distinguish different object types:

relkindObject TypeScaffolded As
'r'Regular tableDatabaseTable
'f'Foreign tableDatabaseTable
'v'ViewDatabaseView
'm'Materialized viewDatabaseView

The query at src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs196-220 also excludes internal schemas (pg_catalog, information_schema) and tables owned by PostgreSQL extensions.

Sources: src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs187-265

Column Detection and Type Mapping

Column scaffolding must detect PostgreSQL-specific features and map them to EF Core concepts.

Identity and Serial Column Detection

The provider detects auto-increment columns in two ways:

Identity Columns (PostgreSQL 10+)

Identity columns are detected via the attidentity column:

attidentityStrategyAnnotation
'a'GENERATED ALWAYSNpgsqlValueGenerationStrategy.IdentityAlwaysColumn
'd'GENERATED BY DEFAULTNpgsqlValueGenerationStrategy.IdentityByDefaultColumn

Associated sequence options (start, increment, min/max) are stored in the NpgsqlAnnotationNames.IdentityOptions annotation src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs412-474

Serial Columns (Legacy)

For serial columns, the factory performs pattern matching on the default value expression at src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs429-446:


If a nextval() pattern is matched on these types, the column is marked with NpgsqlValueGenerationStrategy.SerialColumn.

Generated Columns

PostgreSQL 12+ supports generated columns. The attgenerated column indicates:

attgeneratedTypeEF Core Properties
's'StoredComputedColumnSql + IsStored = true
'v'VirtualComputedColumnSql + IsStored = false

Sources: src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs393-409

Code Generation with NpgsqlAnnotationCodeGenerator

NpgsqlAnnotationCodeGenerator converts model annotations into fluent API method calls in the generated DbContext.

Annotation to Fluent API Mapping


Sources: src/EFCore.PG/Design/Internal/NpgsqlAnnotationCodeGenerator.cs13-447

Value Generation Strategy Code Generation

The code generator has special logic for value generation strategies at src/EFCore.PG/Design/Internal/NpgsqlAnnotationCodeGenerator.cs323-384:

StrategyGenerated Method
SerialColumn.UseSerialColumn()
IdentityAlwaysColumn.UseIdentityAlwaysColumn()
IdentityByDefaultColumn.UseIdentityByDefaultColumn()

Convention Handling: Both SerialColumn and IdentityByDefaultColumn are considered by-convention, so they're only generated if explicitly different from the convention src/EFCore.PG/Design/Internal/NpgsqlAnnotationCodeGenerator.cs179-201

Filtering and Options

The scaffolding process supports filtering via DatabaseModelFactoryOptions.

Schema and Table Filtering: The factory parses table names using a regex at src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs22-32 to support quoted identifiers and schema-qualified names.

Sources: src/EFCore.PG/Scaffolding/Internal/NpgsqlDatabaseModelFactory.cs94-147 test/EFCore.PG.FunctionalTests/Scaffolding/NpgsqlDatabaseModelFactoryTest.cs351-459


Sources: