-
Notifications
You must be signed in to change notification settings - Fork 226
Settings.PrependSchemaNameForTable
Decides, table by table, whether the schema name is prepended to the generated class name.
| Type |
Func<Table, bool> - return true to prepend, false to leave the name alone |
| Default | Returns true for every table |
| Applies to | EF 6 and EF Core |
| Databases | Databases with real schemas: SQL Server, PostgreSQL, Oracle. MySQL has no schema within a database, and SQLite is always main
|
In Database.tt? |
No. You have to add it yourself |
This setting is not in the shipped
Database.tt, so most people never find out it exists. If you have ever turnedSettings.PrependSchemaNameoff entirely because one schema was annoying you, this is the setting you wanted instead.
When two schemas contain a table with the same name, dbo.Order and sales.Order cannot both generate a
class called Order. So by default the generator prepends the schema to every table outside the default
schema: sales.Order becomes sales_Order.
That is the right call when there is a genuine clash, and clumsy when there is not. sales_Order,
sales_Customer, sales_Invoice reads badly if nothing in dbo shares those names.
Settings.PrependSchemaName is the blunt version - it turns prepending off for every table at once, and then
a real clash silently generates two classes with the same name. PrependSchemaNameForTable is the per-table
version: keep prepending on, and exempt the tables where you know there is no clash.
The callback is only consulted for tables outside the default schema. Tables in the default schema
(dbo on SQL Server, public on PostgreSQL) are never prepended and never reach it.
The sample schema has dbo.Category, dbo.Product and sales.Order.
public interface IMyDbContext : IDisposable
public class MyDbContext : DbContext, IMyDbContext
public class MyDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
public class Category
public class Product
public class sales_Order
public class CategoryConfiguration : IEntityTypeConfiguration<Category>
public class ProductConfiguration : IEntityTypeConfiguration<Product>
public class sales_OrderConfiguration : IEntityTypeConfiguration<sales_Order>Settings.PrependSchemaNameForTable = delegate(Table table)
{
// Nothing in dbo is called Order, so the prefix buys nothing here
return !table.Schema.DbName.Equals("sales", StringComparison.OrdinalIgnoreCase);
};public interface IMyDbContext : IDisposable
public class MyDbContext : DbContext, IMyDbContext
public class MyDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
public class Category
public class Order
public class Product
public class CategoryConfiguration : IEntityTypeConfiguration<Category>
public class OrderConfiguration : IEntityTypeConfiguration<Order>
public class ProductConfiguration : IEntityTypeConfiguration<Product>sales_Order became Order. The database mapping is untouched - the configuration still says
builder.ToTable("Order", "sales") - so this only changes the C# name.
- One tidy schema among several. Exempt the one you use constantly, keep the prefix on the rest.
- A legacy schema you are migrating away from. Prefix the old one, leave the new one clean.
-
Reserved-word schemas. A schema literally named
dboin a non-SQL-Server database, or one whose name is not a legal C# identifier prefix.
A common shape is an allow-list:
Settings.PrependSchemaNameForTable = table =>
{
var clean = new[] { "sales", "reporting" };
return !clean.Contains(table.Schema.DbName, StringComparer.OrdinalIgnoreCase);
};Name clashes become your problem. Exempt sales while dbo.Order also exists and you generate two
classes called Order in one namespace. The generator does not detect this; the C# compiler does, and its
error points at the generated file.
The schema is prepended exactly as the database spells it, not PascalCased. sales.Order becomes
sales_Order, not Sales_Order, and the singularisation still applies to the table part. If you want a
different shape entirely, use Settings.TableRename instead - it
runs earlier and controls the whole name.
Settings.PrependSchemaName = false overrides this callback completely. The callback is only reached when
PrependSchemaName is true. If prepending is off globally, this delegate never runs.
Foreign key navigation properties do not consult it. The class name a foreign key points at is derived
separately and honours Settings.PrependSchemaName but not this per-table callback, so a relationship
crossing into an exempted schema can still name the prefixed form. Check the generated navigation properties
after exempting a schema that other schemas point at.
Stored procedures have their own callback, Settings.PrependSchemaNameForStoredProcedure, with the same
shape and the same default.
- Settings.PrependSchemaName - the global switch this refines
- Settings.DefaultSchema - which schema is never prepended
- Settings.TableRename - full control over the generated name
- Settings Reference
- 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