Skip to content

EF Core Data Annotations — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about EF Core Data Annotations. We cover key concepts, practical examples, and best practices.

You need to configure your EF Core model but want the configuration close to the entity definition. Data annotations are attributes placed directly on entity classes and properties, providing a simple, discoverable way to configure your model.

Wrong

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

Output: EF Core uses conventions. Id becomes PK. Name is nvarchar(max). No constraints, no column type precision.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

[Table("tbl_Products")]
public class Product
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Column("ProductId")]
    public int Id { get; set; }

    [Required(ErrorMessage = "Name is required")]
    [MaxLength(200)]
    [Index(IsUnique = true)]
    public string Name { get; set; }

    [Column(TypeName = "decimal(18,2)")]
    [Range(0, 999999.99)]
    public decimal Price { get; set; }

    [ForeignKey("Category")]
    public int CategoryId { get; set; }

    [NotMapped]
    public string DisplayName => $"{Name} ({Price:C})";
}

Prevention

  • Use [Key] for primary key, [DatabaseGenerated] for identity/calculated columns.
  • Use [Required] for non-nullable columns, [MaxLength] for string column sizes.
  • Use [Column] for custom column names and types.
  • Use [Table] for custom table names.
  • Use [ForeignKey] to specify navigation property relationship.
  • Use [NotMapped] for properties that should not be persisted.
  • Use [Index] (EF Core 5+) to create database indexes.

Common Mistakes with core data annotation

  1. Using foldl instead of foldl' causing stack overflow on large lists
  2. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  3. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable

These mistakes appear frequently in real-world EF code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

What is the most commonly used data annotation?

[Key] for primary key specification when the property name does not follow conventions. [Required] and [MaxLength] for string column constraints. [ForeignKey] for relationship configuration in simple models.

Can I create composite keys with data annotations?

Yes, but it requires a dedicated class: add [PrimaryKey(nameof(OrderId), nameof(ProductId))] on the entity class (EF Core 7+). For older versions, use Fluent API: entity.HasKey(e => new { e.OrderId, e.ProductId }).

Do data annotations affect validation or only database schema?

[Required], [MaxLength], and [Range] affect both EF Core schema generation and ASP.NET Core model validation. The same attributes serve dual purpose — database constraints and input validation. [Column] and [Table] are schema-only.

Learn more about EF Core data annotations at DodaTech.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro