-
Notifications
You must be signed in to change notification settings - Fork 226
Settings.UseDataAnnotations
Adds [Key], [Required], [MaxLength] and friends to the generated properties, alongside the Fluent API configuration.
| Type | bool |
| Default | false |
| Applies to | EF 6 and EF Core |
| Databases | All |
In Database.tt? |
Yes |
EF can be told about a model two ways: data annotations, which are attributes on the properties, and the
Fluent API, which is the builder.Property(...) code in the configuration class. This generator always
writes the Fluent API. This setting adds the annotations as well.
Turning it on gives you, automatically:
| Situation | Attribute |
|---|---|
| Primary key column | [Key, Column(Order = n)] |
| Non-nullable column |
[Required], or [Required(AllowEmptyStrings = true)] for a string |
| String with a length |
[MaxLength(n)] and [StringLength(n)]
|
nvarchar(max) |
[MaxLength] with no argument |
rowversion / timestamp
|
[Timestamp, ConcurrencyCheck] |
| Every column |
[Display(Name = "...")], from the humanised column name |
SQL Server 2025 vector
|
[Column(TypeName = "vector(n)")] |
System.ComponentModel.DataAnnotations and .Schema are added to the using list for you.
// Product
public class Product
{
public int ProductId { get; set; } // ProductId (Primary key)
public string ProductName { get; set; } // ProductName (length: 100)
public decimal UnitPrice { get; set; } // UnitPrice
public string Notes { get; set; } // Notes
public int CategoryId { get; set; } // CategoryId
public string DisplayLabel { get; private set; } // DisplayLabel (length: 150)
// Foreign keys
/// <summary>
/// Parent Category pointed by [Product].([CategoryId]) (FK_Product_Category)
/// </summary>
public Category Category { get; set; } // FK_Product_Category
public Product()
{
UnitPrice = 0m;
}
} // Product
[Table("Product", Schema = "dbo")]
public class Product
{
[Key, Column(Order = 1)]
[Required]
[Display(Name = "Product ID")]
public int ProductId { get; set; } // ProductId (Primary key)
[MaxLength(100)]
[StringLength(100)]
[Required(AllowEmptyStrings = true)]
[Display(Name = "Product name")]
public string ProductName { get; set; } // ProductName (length: 100)
[Required]
[Display(Name = "Unit price")]
[Precision(18, 2)]
public decimal UnitPrice { get; set; } // UnitPrice
[Display(Name = "Notes")]
public string Notes { get; set; } // Notes
[Required]
[Display(Name = "Category ID")]
public int CategoryId { get; set; } // CategoryId
[MaxLength(150)]
[StringLength(150)]
[Display(Name = "Display label")]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public string DisplayLabel { get; private set; } // DisplayLabel (length: 150)
// Foreign keys
/// <summary>
/// Parent Category pointed by [Product].([CategoryId]) (FK_Product_Category)
/// </summary>
public Category Category { get; set; } // FK_Product_Category
public Product()
{
UnitPrice = 0m;
}
}The Fluent API configuration is unchanged in both cases - the annotations are additional, not a replacement.
Turn it on when something other than EF reads the attributes. That is the real reason to want them:
-
ASP.NET model validation uses
[Required],[MaxLength]and[StringLength]when binding a form or a request body to an entity. - Swagger / OpenAPI generators read them to describe request schemas.
-
UI frameworks - Blazor's
DataAnnotationsValidator, older MVC scaffolding - work from them directly. -
[Display(Name = ...)]gives every property a human-readable label, which those same UI frameworks use.
Leave it off if only EF reads your model. The Fluent API already says all of it, so the attributes are duplication, and duplication that can disagree with itself.
Do not validate an entity against these attributes and expect it to mean something. [Required] on a
non-nullable column is a statement about the database, not about your business rules. A column that is NOT NULL with a default is [Required] here and perfectly fine to leave unset in your code.
[Required(AllowEmptyStrings = true)] is deliberate. A NOT NULL string column happily stores '', so
[Required] without that argument would reject a value the database accepts. If you want empty strings
rejected, that is a business rule and belongs in a validator, not in generated code.
Annotations and the Fluent API can disagree, and the Fluent API wins. If you edit an annotation by hand in
a partial class, EF keeps using the generated builder.Property(...). Change the Fluent API too, or the model
will not match what you read.
[Display] on every column is noisy. It is genuinely useful for UI scaffolding and pure clutter
otherwise. To keep the rest without it, leave this setting off and call
Settings.ApplyDataAnnotations(column) selectively from
Settings.UpdateColumn.
Adding your own attributes does not need this setting. column.Attributes.Add("[MyAttribute]") in
UpdateColumn works regardless. See Data Annotations.
-
Data Annotations - custom attributes,
[JsonPropertyName]from extended properties, and more -
Settings.UpdateColumn - adding attributes yourself, and where
ApplyDataAnnotationsis called - Settings.AdditionalNamespaces
- Settings Reference
- Settings A-Z - every setting, with a page each
- Common Settings Types Explained
- Settings Callbacks
- Settings runtime values and helpers
- Filtering
- Full Control Over the Generated Code
- Enum Generation from Table Data
- Owned Entities
- JSON column support
- Global Query Filters
- Extended Property Names Feature
- Partial Properties
- File-Scoped Namespaces
- Data Annotations
- Spatial Types
- HierarchyId
- RowVersion and TimeStamp columns
- Lazy Loading
- Stored proc result sets
- Custom File-Based Templates
- Extra entities via partial classes
- INotifyPropertyChanged
- Syntax colour for T4