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:
- Public properties with a getter and setter of a primitive CLR type (like
int,string,DateTime) are considered properties. - Properties named
Idor<ClassName>Idare automatically configured as the primary key. - Classes with a public constructor and no parameters are considered entity types.
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
[Key]: Marks a property as the primary key.[Required]: Marks a property as required (not nullable in the database).[MaxLength(n)]: Specifies the maximum length for string properties.[Column("ColumnName")]: Specifies the name of the database column.[ForeignKey("RelatedEntity")]: Identifies a foreign key property.[InverseProperty("NavigationProperty")]: Configures the navigation property on the other side of a relationship.
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; }
}
Entity Types
An entity type represents a table in your database. EF Core discovers entity types through several mechanisms:
DbSet<TEntity>properties on yourDbContext.- Entities discovered by convention (e.g., classes that EF Core can map to tables).
- Entities explicitly configured in
OnModelCreating.
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.
- One-to-One:
public UserProfile Profile { get; set; } - One-to-Many:
public ICollection<Order> Orders { get; set; } - Many-to-One:
public User User { get; set; } - Many-to-Many: Often configured implicitly through join entities or explicitly using the Fluent API.
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) |
|---|---|
|
|
This is a one-to-many relationship where one Blog can have many Posts.