Skip to content

Generating Multiple Database Contexts in a Single Go

Simon Hughes edited this page Mar 20, 2026 · 1 revision

This enterprise feature reads filter and settings data from database tables and generates many DbContext classes in one pass. The database schema is read once; hundreds of contexts can be produced with separate namespaces and access rules.

Use case: High-security microservice architectures where each API should only have access to the tables and columns it strictly needs.

Setup

Step 1: Run the SQL Script

Run the setup SQL script to create the settings tables in your database:

MultiContextSettings.sql

Step 2: Configure Database.tt

Settings.DatabaseType     = DatabaseType.SqlServer;
Settings.TemplateType     = TemplateType.EfCore10; // Or Ef6, EfCore8, EfCore9
Settings.GeneratorType    = GeneratorType.EfCore;  // Or Ef6
Settings.UseMappingTables = false;
Settings.FileManagerType  = FileManagerType.EfCore;
Settings.ConnectionString = "Data Source=(local);Initial Catalog=EfrpgTest;Integrated Security=True;Encrypt=false;TrustServerCertificate=true";
Settings.ConnectionStringName = "MyDbContext";
Settings.GenerateSeparateFiles = false;
Settings.Namespace = DefaultNamespace;
Settings.AddUnitTestingDbContext = false;

// Enable multi-context mode
Settings.GenerateSingleDbContext = false;

// Connection string to the database containing multi-context settings
// Leave empty to read from the same database as ConnectionString
Settings.MultiContextSettingsConnectionString = "Data Source=(local);Initial Catalog=EfrpgTest_Settings;Integrated Security=True;Encrypt=false;TrustServerCertificate=true";

Tip: Set Settings.GenerateSeparateFiles = false when multiple contexts share identical table names to prevent generated class files from overwriting each other.

Custom Column Attributes

You can add custom data annotations to columns via the settings database. Use a tilde ~ as the delimiter between multiple attributes:

UPDATE MultiContext.[Column]
SET Attributes = '[ExampleForTesting("abc")]~[CustomRequired]'
WHERE Name = 'Dollar';

File-Based Templates

Use file-based templates for full control over generated code:

Settings.TemplateType   = TemplateType.FileBasedCore10;
Settings.TemplateFolder = @"C:\path_to_templates";
// Or relative:
Settings.TemplateFolder = Path.Combine(Settings.Root, "Templates");

Override the template folder per individual context:

UPDATE MultiContext.Context
SET TemplatePath = 'C:\path\to\context_specific_templates'
WHERE [Name] = 'context_name';

Custom Extra Columns

You can add extra columns to the MultiContext.[Column], MultiContext.[Table], and MultiContext.[StoredProcedure] tables for custom processing:

ALTER TABLE MultiContext.[Column] ADD Notes VARCHAR(500) NULL;
ALTER TABLE MultiContext.[Column] ADD Priority INT NULL;

Then process them in Database.tt:

Settings.MultiContextAllFieldsColumnProcessing = delegate (Column column, Table table, Dictionary<string, object> allFields)
{
    if (allFields.ContainsKey("Priority"))
    {
        var priority = (int) allFields["Priority"];
        column.ExtendedProperty += $" Priority={priority}";
    }
};

Similarly for tables and stored procedures:

Settings.MultiContextAllFieldsTableProcessing = delegate (Table table, Dictionary<string, object> allFields)
{
    if (allFields.ContainsKey("Notes"))
        table.AdditionalComment = allFields["Notes"].ToString();
};

Settings.MultiContextAllFieldsStoredProcedureProcessing = delegate (StoredProcedure sp, Dictionary<string, object> allFields)
{
    if (allFields.ContainsKey("CustomRename"))
        sp.NameHumanCase = allFields["CustomRename"].ToString();
};

Multi-Context Settings Delimiter

The delimiter used to split multiple attribute values in the settings database:

Settings.MultiContextAttributeDelimiter = '~'; // Default

Custom Settings Plugin

For advanced scenarios, you can provide a custom plugin to read multi-context settings:

Settings.MultiContextSettingsPlugin = "c:\\Path\\YourPlugin.dll,Full.Name.Of.Class.Including.Namespace";

Clone this wiki locally