Modeling Entity Types

This section details how to define and configure your domain models to be used by Entity Framework Core.

Convention over Configuration

EF Core follows a set of conventions to automatically configure your entity types. This means that in many cases, you don't need to explicitly configure anything. For example:

While conventions are helpful, you often need to override them or provide more specific configurations.

Data Annotations

Data Annotations provide a way to configure your model directly on the entity classes using attributes. This is often the simplest approach for straightforward configurations.

Common Data Annotations

Example:


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

public class Product
{
    [Key]
    public int ProductId { get; set; }

    [Required]
    [MaxLength(100)]
    public string Name { get; set; }

    [Column("DescriptionText")]
    public string Details { get; set; }

    public decimal Price { get; set; }
}
        

Fluent API

The Fluent API allows for more advanced and centralized configuration of your model. It's defined in the OnModelCreating method of your DbContext.

Configuring with Fluent API

You use the ModelBuilder object to configure your entities.

Example:


using Microsoft.EntityFrameworkCore;

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Configure Blog entity
        modelBuilder.Entity<Blog>()
            .HasKey(b => b.BlogId);

        modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .IsRequired()
            .HasMaxLength(200);

        // Configure Post entity
        modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b.Posts)
            .HasForeignKey(p => p.BlogId);

        // Example of table configuration
        modelBuilder.Entity<Post>().ToTable("BlogPosts");
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}
        
Tip: You can use both Data Annotations and the Fluent API. The Fluent API configurations will override Data Annotations where there is a conflict.

Entity Types

An entity type represents a table in your database. EF Core discovers entity types through several mechanisms:

Properties

Properties of an entity type are mapped to columns in the database table. EF Core determines which properties to include in the model based on conventions and configuration.

Scalar Properties

These are properties that are mapped to database columns (e.g., int, string, DateTime, decimal). They are typically public with a getter and setter.

Navigation Properties

These are properties that represent relationships to other entity types. They can be single entities or collections.

Relationships

EF Core supports configuring various types of relationships between entity types:

Primary Keys

Every entity type must have a primary key. EF Core can infer it by convention (e.g., Id property) or you can explicitly configure it using [Key] or the Fluent API.

Foreign Keys

Foreign keys link related entities. They can be configured using [ForeignKey] or the Fluent API.

Inverse Properties

Configuring the inverse navigation property ensures that EF Core can correctly track relationships. This is often done with [InverseProperty] or the Fluent API's HasPrincipalKey and HasForeignKey.

One-to-Many Relationship Example:

Entity 1 (Blog) Entity 2 (Post)

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public ICollection<Post> Posts { get; set; } // Navigation property
}
                        

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public int BlogId { get; set; } // Foreign Key
    public Blog Blog { get; set; } // Navigation property
}
                        

This is a one-to-many relationship where one Blog can have many Posts.

← Previous: Concepts Next: Migrations →