-
Notifications
You must be signed in to change notification settings - Fork 226
SQL Server
SQL Server is the reference implementation. Everything the generator can do, it can do here.
Practical floor is SQL Server 2012, because sequence reading uses sys.sequences. Against anything older
the sequence read fails on its own and the tool returns partial results rather than giving up; everything else
still comes through.
v4 note. If you used v3 you may remember editing
machine.configor runninggacutilfor the other dialects. None of that applies any more, to any database. Theefrpgtool shipsMicrosoft.Data.SqlClientas an ordinary NuGet dependency. Install the tool and you are done:dotnet tool install -g Efrpg.
Settings.DatabaseType = DatabaseType.SqlServer;
Settings.TemplateType = TemplateType.EfCore10; // or EfCore9, EfCore8, Ef6
Settings.GeneratorType = GeneratorType.EfCore; // or GeneratorType.Ef6
Settings.ConnectionString = "Data Source=(local);Initial Catalog=Northwind;Integrated Security=True;Encrypt=false;TrustServerCertificate=true";Your project needs Microsoft.EntityFrameworkCore.SqlServer (EF Core) or EntityFramework (EF 6).
For Azure SQL, Entra ID and the other connection string shapes, see Connection strings.
db_datareader plus VIEW DEFINITION on the database is enough to read tables, views, columns, keys, indexes,
triggers, sequences, synonyms and extended properties.
EXECUTE on your stored procedures is additionally required if you want return models generated for them (see
below). db_ddladmin is the blunt instrument that covers everything, if you are stuck arguing with a DBA.
| Feature | Supported | Notes |
|---|---|---|
| Tables, views, columns | ✔ | |
| Primary and foreign keys | ✔ | Including composite and self-referencing |
| Indexes | ✔ | Including unique, clustered and INCLUDE columns |
| Identity columns | ✔ | |
| Computed columns | ✔ | Given a private setter when Settings.UsePrivateSetterForComputedColumns = true
|
| Default constraints | ✔ | Emitted as property initialisers, and as .HasDefaultValueSql() when Settings.GenerateHasDefaultValueSql = true
|
| Extended properties | ✔ (not Azure SQL) | Emitted as XML doc comments and readable in your own callbacks. See Extended Property Names Feature |
| Stored procedures | ✔ | Including multiple result sets, and input/output parameters |
| Table-valued functions | ✔ | EF 6 also needs the EntityFramework.CodeFirstStoreFunctions NuGet package |
| Scalar-valued functions | ✔ | |
| Synonyms | ✔ | Including cross-database synonyms. Opt in with FilterSettings.IncludeSynonyms = true
|
| Sequences | ✔ | Wire them to identity columns with Settings.HiLoSequences
|
| Triggers | ✔ | Emitted as .ToTable(tb => tb.HasTrigger("...")) where EF Core needs it |
| Temporal tables | SQL Server 2016+ | Detected from the server version |
| Memory-optimised tables | ✔ | Via sys.tables.is_memory_optimized
|
json and vector types |
SQL Server 2025+ / Azure SQL | Detected from the server version |
| Spatial types | ✔ | See Spatial Types |
hierarchyid |
✔ | See HierarchyId |
rowversion / timestamp
|
✔ | See RowVersion and TimeStamp columns |
| Multi-context settings tables | ✔ | SQL Server only. See Generating Multiple Database Contexts in a Single Go |
Azure SQL Database does not report extended properties. That read is skipped on Azure, so column descriptions will not appear as comments. Everything else works normally.
This one surprises people, so it is worth stating plainly.
To work out what a stored procedure returns, the generator executes it with SET FMTONLY ON. In that mode
SQL Server returns column metadata without running the statements, so no rows are produced and nothing is
written. It is a metadata call, not a real execution - but it does mean the connecting account needs EXECUTE.
SET FMTONLY is an old feature with old edges. Procedures that build temp tables, or use dynamic SQL, can
report the wrong shape or no shape at all. Four escape hatches, in the order I would try them:
-
Tell the generator the procedure returns an entity you already have:
Settings.StoredProcedureReturnTypes.Add("SalesByYear", "SummaryOfSalesByYear");
-
Declare the shape by hand in
Settings.ReadStoredProcReturnObjectException. See Stored Procedure Return Model Errors. -
Exclude just that procedure:
FilterSettings.StoredProcedureFilters.Add(new RegexExcludeFilter("^usp_Awkward$"));
-
Turn off procedure reading entirely:
FilterSettings.IncludeStoredProcedures = false; FilterSettings.IncludeTableValuedFunctions = false; FilterSettings.IncludeScalarValuedFunctions = false;
Option 4 is also the single biggest speed-up available on a large database.
Multiple schemas are read in one pass. By default the schema name is prepended to the generated class name so
that dbo.Order and sales.Order do not collide:
-
dbo.HellobecomesHello-dbois never prepended -
abc.Hellobecomesabc_Hello
Note the schema keeps the case the database gives it. It is prepended verbatim, unlike the table name, which is singularised and PascalCased.
Turn it off with Settings.PrependSchemaName = false, or control it per table with
Settings.PrependSchemaNameForTable.
To read only some schemas:
FilterSettings.SchemaFilters.Add(new RegexIncludeFilter("^dbo$|^sales$"));Two things to try, in this order:
- Turn off stored procedures, TVFs and scalar functions as shown above. Reading procedure result shapes is by far the slowest part of a run, and this usually accounts for all of it.
- Update the statistics on the system tables. A real, well-documented SQL Server problem, and the fix takes seconds: Speed up Reverse generating by updating statistics on sys tables.
On SQL Server 2014 specifically there was a faulty query plan optimisation that could make schema reads appear
to hang. If you are still on it, set Settings.IncludeQueryTraceOn9481Flag = true (you will need elevated
privileges).
Filtering down to the tables you actually need is worth doing regardless: a DbContext with 40 entities builds
its model faster at run time than one with 900. See Filtering.
- 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