Skip to content

Settings.MappingTableRename

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

Settings.MappingTableRename

Names the collection properties that come from a many-to-many mapping table, which matters when two mapping tables link the same pair of entities.

Type Func<string, string, string, string>
Parameters (mappingTable, tableName, entityName)
Default Returns entityName unchanged
Applies to EF 6 mainly - see gotchas
Databases All
In Database.tt? Yes, with a commented-out example

What it does

When Settings.UseMappingTables is on, a pure join table is mapped implicitly and each side gains a collection of the other. Name that collection after the other entity - User.Skills - and it is fine, right up until there are two join tables between the same pair:

CREATE TABLE dbo.UserRequiredSkills (UserId int, SkillId int);
CREATE TABLE dbo.UserOptionalSkills (UserId int, SkillId int);

Both produce User.Skills and Skill.Users, which does not compile. This callback is how you tell them apart:

Settings.MappingTableRename = delegate(string mappingTable, string tableName, string entityName)
{
    if (mappingTable == "UserRequiredSkills" && tableName == "User")
        return "RequiredSkills";

    if (mappingTable == "UserOptionalSkills" && tableName == "User")
        return "OptionalSkills";

    return entityName;   // Default for everything else
};

The three parameters: mappingTable is the join table's name, tableName is the entity the property is being added to, and entityName is the name that would be used - which is what you return when your rule does not apply.

When to use it

Two mapping tables between the same pair. The reason it exists, and the only case where you have no choice.

A join table whose name reads better than the entity's. Order.Products through an OrderLine table is correct and Order.Lines may be what your domain calls it.

Gotchas

It only fires for implicitly mapped tables. With Settings.UseMappingTables = false - which is the default, and mandatory for EF Core - join tables are generated as ordinary entities and there is no implicit collection to name. This callback then does nothing, and nothing tells you so.

On EF Core, name the navigation properties with Settings.ForeignKeyName instead.

A table only counts as a mapping table if it has nothing but the two foreign keys. Any third column and it is generated as an entity regardless.

Always return something. null or empty generates a property with no name.

Both ends need a rule. The callback is called once per side, with tableName telling you which. Handle only "User" and the Skill end keeps the default name.

See also

Clone this wiki locally