Skip to content

Settings.PrependSchemaNameForStoredProcedure

Simon Hughes edited this page Aug 30, 2026 · 1 revision

Settings.PrependSchemaNameForStoredProcedure

Decides, procedure by procedure, whether the schema name is prepended to the generated method name.

Type Func<StoredProcedure, bool> - return true to prepend, false to leave the name alone
Default Returns true for every stored procedure
Applies to EF 6 and EF Core
Databases SQL Server, PostgreSQL and Oracle. MySQL has no schema within a database, and SQLite has no stored procedures
In Database.tt? No. You have to add it yourself

Not in the shipped Database.tt, so most people never discover it. It is the per-procedure twin of Settings.PrependSchemaNameForTable.

What it does

Two schemas can both contain a procedure called GetOrderTotals. They cannot both generate a method called GetOrderTotals, so by default the generator prepends the schema to any procedure outside the default schema: sales.GetOrderTotals becomes sales_GetOrderTotals.

When there is no clash that prefix is just noise, and it is noise you type at every call site. This callback lets you keep the prefixing on and exempt the procedures where you know it is unnecessary.

It is only consulted for procedures outside the default schema. Anything in dbo (or public, or the connected Oracle user) is never prepended and never reaches the callback.

Example

The extras schema has dbo.GetStudentsByCourse and sales.GetOrderTotals. These are the generated methods on the DbContext interface, with the async and out-parameter overloads left out for brevity.

Default - the sales procedure is prefixed

List<GetStudentsByCourseReturnModel> GetStudentsByCourse(int? courseId);
List<sales_GetOrderTotalsReturnModel> sales_GetOrderTotals(int? year);

Exempting the sales schema

Settings.PrependSchemaNameForStoredProcedure = delegate(StoredProcedure sp)
{
    // Nothing in dbo is called GetOrderTotals, so the prefix buys nothing
    return !sp.Schema.DbName.Equals("sales", StringComparison.OrdinalIgnoreCase);
};
List<GetOrderTotalsReturnModel> GetOrderTotals(int? year);
List<GetStudentsByCourseReturnModel> GetStudentsByCourse(int? courseId);

Both the method and its return model lose the prefix: sales_GetOrderTotalsReturnModel becomes GetOrderTotalsReturnModel. The generated SQL still calls [sales].[GetOrderTotals], so only the C# name changes.

When to use it

  • One schema you call constantly. Exempt it; keep the prefix on the rest as a safety net.
  • A reporting or integration schema whose procedure names are already unique and already verbose.
  • Procedures whose schema name is not a tidy identifier prefix, such as a schema named after a team or a release.

An allow-list is the usual shape:

Settings.PrependSchemaNameForStoredProcedure = sp =>
{
    var clean = new[] { "sales", "reporting" };
    return !clean.Contains(sp.Schema.DbName, StringComparer.OrdinalIgnoreCase);
};

Gotchas

Name clashes become your problem. Exempt sales while dbo.GetOrderTotals also exists and you generate two methods with the same signature on one interface. The generator does not check; the compiler does.

The schema is prepended verbatim. sales.GetOrderTotals becomes sales_GetOrderTotals, not Sales_GetOrderTotals. To reshape the name entirely, use Settings.StoredProcedureRename, which runs earlier and controls the whole name.

Settings.PrependSchemaName = false overrides it completely. The callback is only reached when PrependSchemaName is true.

It does not rename the return model on its own - the model name is derived from the procedure name, so it follows along. If you want to control that separately, use Settings.StoredProcedureReturnModelRename.

See also

Clone this wiki locally