Skip to content

Settings.Enumerations

Simon Hughes edited this page Sep 10, 2026 · 2 revisions

Turns the rows of a lookup table into a real C# enum, and the five settings that control it.

Setting Type Role
Settings.Enumerations List<EnumerationSettings> Declares which tables become enums
Settings.AddEnum Action<Table> Decides programmatically, per table
Settings.UpdateEnum Action<Enumeration> Attributes on the generated enum
Settings.UpdateEnumMember Action<EnumerationMember> Attributes on each member
Settings.AddEnumDefinitions Action<List<EnumDefinition>> Replaces a column's type with an enum
Settings.UsePascalCaseForEnumMembers bool Whether member names are PascalCased

All apply to EF 6 and EF Core, on every database, and all are in Database.tt.

Two different features

They are easy to confuse.

Generating an enum from table rows is Settings.Enumerations. A DaysOfWeek table with a TypeId and a TypeName column becomes:

public enum DaysOfWeek
{
    Monday = 1,
    Tuesday = 2,
    ...
}

Replacing a column's type with an enum is Settings.AddEnumDefinitions. An OrderHeader.OrderStatus column typed tinyint becomes public OrderStatusType OrderStatus { get; set; }. The enum can be one you generated, or one you wrote by hand.

You often want both: generate the enum from the lookup table, then use it as the type of the foreign key column that points at it.

Settings.Enumerations

Settings.Enumerations = new List<EnumerationSettings>
{
    new EnumerationSettings
    {
        Name       = "DaysOfWeek",          // The enum to generate
        Table      = "EnumTest.DaysOfWeek", // Schema.TableName
        NameField  = "TypeName",            // Column holding the member names
        ValueField = "TypeId"               // Column holding the values
    }
};

EnumerationSettings also has:

Field Purpose
GroupField For a table holding several enums. Put {GroupField} in Name, e.g. "{GroupField}Enum"
DescriptionField A column whose text becomes a [Description("...")] attribute on each member
GenerateDescriptionFromName Generates a [Description] from the member name where DescriptionField gives nothing
AllFields Every column of the row, for use in UpdateEnumMember

Full worked examples on Enum Generation from Table Data.

Settings.AddEnum

Rather than listing tables by hand, decide by rule:

Settings.AddEnum = delegate(Table table)
{
    if (table.HasPrimaryKey &&
        table.PrimaryKeys.Count() == 1 &&
        table.NameHumanCase.EndsWith("Enum", StringComparison.InvariantCultureIgnoreCase))
    {
        Settings.Enumerations.Add(new EnumerationSettings
        {
            Name       = table.NameHumanCase.Replace("Enum", "") + "Enum",
            Table      = table.Schema.DbName + "." + table.DbName,
            NameField  = table.Columns.First(x => x.PropertyType == "string").DbName,
            ValueField = table.PrimaryKeys.Single().DbName
        });

        table.RemoveTable = true; // Do not also generate a POCO for it
    }
};

Settings.ElementsToGenerate must contain both Elements.Poco and Elements.Enum for this to work.

UpdateEnum and UpdateEnumMember

Settings.UpdateEnum       = e => e.EnumAttributes.Add("[DataContract]");
Settings.UpdateEnumMember = m =>
{
    m.Attributes.Add("[EnumMember]");

    // AllValues holds every column of the source row
    if (m.AllValues.ContainsKey("SortOrder"))
        m.Attributes.Add(string.Format("[Display(Order = {0})]", m.AllValues["SortOrder"]));
};

Settings.UsePascalCaseForEnumMembers

Default true. Member names come from data, and data is rarely written in C# style - "IN PROGRESS", "on_hold". With this on they become InProgress and OnHold; with it off they are used as-is, with illegal characters stripped.

It is separate from Settings.UsePascalCase precisely because you might want your tables PascalCased and your enum members left exactly as the data has them.

Gotchas

Enum generation reads rows, so it needs a live database. The efrpg tool is invoked a second time to select the values. That is the only part of generation that reads data rather than schema, and it will not work against a database you can only read metadata from.

Set table.RemoveTable = true or you get both. A table that becomes an enum will otherwise also generate a POCO and a DbSet, which is almost never wanted.

Table is "Schema.TableName", one string. Omitting the schema works only for the default schema.

Duplicate or illegal member names break the build. Two rows whose names PascalCase to the same identifier, or a name that is a C# keyword, produce an enum that does not compile. Data changes and your build breaks - which is an argument for DescriptionField over creative naming.

Values must be whole numbers. ValueField has to be an integral column. A string value field works only where the strings parse as integers.

AddEnumDefinitions needs Settings.ApplyEnumTypeReplacement to be called. The shipped Settings.UpdateColumn calls it at the end. Replace UpdateColumn and drop that call, and the type replacement silently stops happening.

See also

Clone this wiki locally