Entity Framework Core: Modeling Data

This document provides a comprehensive guide to modeling your data using Entity Framework Core (EF Core). EF Core enables you to work with relational data in your .NET applications using a model that is familiar to you as object-oriented programmers. This involves defining your domain entities and establishing the relationships between them.

Entities

Entities are plain old CLR objects (POCOs) that represent the fundamental building blocks of your application's domain. EF Core uses these objects to interact with the database. Each entity typically maps to a table in the database.

Defining an Entity

An entity is simply a class with properties that represent the data you want to store. EF Core uses conventions to discover these entities and their properties.


public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public string Name { get; set; }

    public virtual 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 virtual Blog Blog { get; set; }
}
            

In the example above, Blog and Post are entity types. EF Core will automatically map BlogId and PostId to primary keys based on naming conventions.

Relationships

Relationships define how your entities are connected. EF Core supports one-to-one, one-to-many, and many-to-many relationships.

One-to-Many Relationship

The example above demonstrates a one-to-many relationship between Blog and Post, where one blog can have many posts.

Many-to-Many Relationship

For many-to-many relationships, EF Core typically uses a join table (also known as a linking table or association table) to manage the relationship.


public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    public int CourseId { get; set; }
    public string Title { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}
            

When configuring this, EF Core will automatically create a join table (e.g., StudentCourses) to link Student and Course entities.

Keys

Keys are crucial for identifying entities and establishing relationships. EF Core supports primary keys and foreign keys.

Primary Keys

By convention, EF Core identifies primary keys based on the following patterns:

You can also explicitly configure the primary key using the Fluent API or Data Annotations.

Foreign Keys

Foreign keys are used to link related entities. In a one-to-many relationship, the "many" side typically contains the foreign key property.


public class Post
{
    // ... other properties
    public int BlogId { get; set; } // Foreign key
    public virtual Blog Blog { get; set; } // Navigation property
}
            

Value Objects

Value objects represent descriptive aspects of the domain that do not have a conceptual identity of their own. They are defined by their attributes. EF Core can map value objects as owned types.


public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public string PostalCode { get; set; }
}

public class Customer
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
    public Address ShippingAddress { get; set; } // Owned entity
}
            

In this case, the Address properties will be mapped as columns in the Customer table.

Inheritance

EF Core supports mapping inheritance hierarchies from your domain model to the database. It supports two main strategies:

Table-per-Hierarchy (TPH) Example


public abstract class Animal
{
    public int AnimalId { get; set; }
    public string Name { get; set; }
}

public class Dog : Animal
{
    public string Breed { get; set; }
}

public class Cat : Animal
{
    public int LivesRemaining { get; set; }
}
            

When using TPH, EF Core will create a single table for Animal, Dog, and Cat, including a discriminator column (e.g., Discriminator) to indicate whether a row represents a Dog or a Cat.

For more advanced modeling scenarios, including configuring relationships, keys, and inheritance in detail, refer to the Advanced Modeling section.