Skip to content

Settings.IncludeComments

Simon Hughes edited this page Aug 30, 2026 · 2 revisions

Settings.IncludeComments and Settings.IncludeExtendedPropertyComments

The two settings that decide what the generated code says about itself, and where those comments go.

Settings.IncludeComments Settings.IncludeExtendedPropertyComments
Type CommentsStyle CommentsStyle
Default CommentsStyle.AtEndOfField CommentsStyle.InSummaryBlock
Source The schema itself Your database's column comments
In Database.tt? Yes Yes

Both take the same enum, and it is not a flags enum - pick one value, do not combine them with |:

public enum CommentsStyle
{
    None,           // No comment
    InSummaryBlock, // /// <summary> above the property
    AtEndOfField    // // after the property, on the same line
}

What they do

Settings.IncludeComments annotates each property with what the generator knows from the schema: the original column name, whether it is a primary key, the string length. It is the trail back to the database when the C# name no longer matches the column name.

Settings.IncludeExtendedPropertyComments carries across the descriptions you wrote in the database - SQL Server extended properties, and the COMMENT ON / COLUMN_COMMENT equivalents on PostgreSQL, MySQL and Oracle. If somebody documented the column in the database, this is what surfaces it in the code.

They are separate because they usually want different treatment. Schema facts are short and belong at the end of the line; a human description is a sentence and belongs in a <summary> block where IntelliSense will show it. That is exactly what the defaults do.

Example: Settings.IncludeComments

CommentsStyle.AtEndOfField (default)

    // Category
    public class Category
    {
        public int CategoryId { get; set; } // CategoryId (Primary key)
        public string CategoryName { get; set; } // CategoryName (length: 50)

        // Reverse navigation

        /// <summary>
        /// Child Products where [Product].[CategoryId] point to this entity (FK_Product_Category)
        /// </summary>
        public ICollection<Product> Products { get; set; } // Product.FK_Product_Category

        public Category()
        {
            Products = new List<Product>();
        }
    }

CommentsStyle.InSummaryBlock

    // Category
    public class Category
    {
        /// <summary>
        /// CategoryId (Primary key)
        /// </summary>
        public int CategoryId { get; set; }

        /// <summary>
        /// CategoryName (length: 50)
        /// </summary>
        public string CategoryName { get; set; }

        // Reverse navigation

        /// <summary>
        /// Child Products where [Product].[CategoryId] point to this entity (FK_Product_Category)
        /// </summary>
        public ICollection<Product> Products { get; set; } // Product.FK_Product_Category

        public Category()
        {
            Products = new List<Product>();
        }
    }

CommentsStyle.None

    public class Category
    {
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }

        // Reverse navigation
        public ICollection<Product> Products { get; set; }

        public Category()
        {
            Products = new List<Product>();
        }
    }

Note that the foreign key documentation stays in all three. That comes from the relationship, not from this setting.

Example: Settings.IncludeExtendedPropertyComments

Document.Title carries a SQL Server extended property: "The title shown to users. Not the file name."

CommentsStyle.InSummaryBlock (default)

    // Document
    public class Document
    {
        public int DocumentId { get; set; } // DocumentId (Primary key)

        /// <summary>
        /// The title shown to users. Not the file name.
        /// </summary>
        public string Title { get; set; } // Title (length: 100)
        public byte[] RowVersion { get; set; } // RowVersion (length: 8)
        public int? ReviewedByUserId { get; set; } // ReviewedByUserId
    }

CommentsStyle.None

    // Document
    public class Document
    {
        public int DocumentId { get; set; } // DocumentId (Primary key)
        public string Title { get; set; } // Title (length: 100)
        public byte[] RowVersion { get; set; } // RowVersion (length: 8)
        public int? ReviewedByUserId { get; set; } // ReviewedByUserId
    }

When to change them

IncludeComments = None if you find the column names redundant - which they are when Settings.UsePascalCase has done nothing more than capitalise them. On a database whose names already look like C#, the comments repeat the property name on every line.

IncludeExtendedPropertyComments = InSummaryBlock is worth keeping even if you turn the other one off. Descriptions written by whoever knows the data are the most valuable comments in the file, they show up in IntelliSense, and they cost you nothing to maintain because they live in the database.

IncludeComments = InSummaryBlock if you generate XML documentation and want the schema facts in it. Be aware it triples the height of every entity.

Gotchas

CommentsStyle is not a flags enum. CommentsStyle.InSummaryBlock | CommentsStyle.AtEndOfField compiles - enums always do - and produces AtEndOfField, because the underlying values are 1 and 2. Pick one.

Extended properties are SQL Server's only named ones. PostgreSQL, MySQL and Oracle have one unnamed comment per object, which arrives under the fixed name Comment. SQLite has none at all. See Extended Property Names Feature.

Azure SQL Database does not report extended properties, so that read is skipped there and this setting has nothing to show.

Both put text into a comment without escaping it. A description containing */ will not end well. This is theoretical for most databases and worth knowing if your descriptions contain code.

Settings.UsePragma is what silences the missing-XML-comment warning. Turning on InSummaryBlock gives most properties a <summary>, but not all of them, and a project with XML docs required will still warn. See Settings.UsePragma.

See also

Clone this wiki locally