Modeling Your Data with Entity Framework

Entity Framework (EF) provides powerful tools for modeling your application's data. This section explores how to define your data models, map them to your database, and leverage EF's capabilities for object-relational mapping (ORM).

Understanding Data Models

A data model is a conceptual representation of the data your application will store and manage. In Entity Framework, this is typically achieved by defining Plain Old CLR Objects (POCOs) that represent your entities. These classes will have properties that correspond to the columns in your database tables.

Entity Classes

Entity classes are the building blocks of your EF model. They represent the core objects in your domain. For example, a simple Product entity might look like this:


public class Product
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int StockLevel { get; set; }
}
            

Relationships Between Entities

EF excels at managing relationships between entities, such as one-to-one, one-to-many, and many-to-many. These relationships are defined by including navigation properties in your entity classes.

Consider a Category entity and its relationship with Product:


public class Category
{
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public virtual ICollection Products { get; set; }
}

public class Product
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int StockLevel { get; set; }
    public int CategoryId { get; set; } // Foreign key
    public virtual Category Category { get; set; } // Navigation property
}
            

Configuring Your Model

Entity Framework uses conventions to infer how your classes map to database tables and columns. However, you can override these conventions and provide explicit configuration using either Data Annotations or the Fluent API.

Data Annotations

Data Annotations are attributes you can apply directly to your entity classes and properties to configure the mapping.


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

public class Product
{
    [Key]
    [Column("ProductID")]
    public int ProductId { get; set; }

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

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

    [Range(0, 1000)]
    public int StockLevel { get; set; }
}
            

Fluent API

The Fluent API provides a more powerful and flexible way to configure your model by overriding methods in your DbContext class.


using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public DbSet Products { get; set; }
    public DbSet Categories { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>()
            .HasKey(p => p.ProductId);

        modelBuilder.Entity<Product>()
            .Property(p => p.Name)
            .IsRequired()
            .HasMaxLength(100);

        modelBuilder.Entity<Product>()
            .Property(p => p.Price)
            .HasColumnType("decimal(18,2)");

        modelBuilder.Entity<Product>()
            .HasOne(p => p.Category)
            .WithMany(c => c.Products)
            .HasForeignKey(p => p.CategoryId);
    }
}
            

DbContext

The DbContext is the primary class for interacting with Entity Framework. It represents a session with the database and allows you to query and save data. You typically derive from DbContext and add properties for each of your entity sets.

Tip: When using the Fluent API, it's common practice to define your entity configurations in separate classes that implement IEntityTypeConfiguration<TEntity> and then apply them in OnModelCreating.

Key Concepts in Modeling

Important: Ensure your entity properties are public with public getters and setters for Entity Framework to access them correctly. Use lazy loading for navigation properties where appropriate to optimize performance.

By mastering these concepts, you can build robust and efficient data access layers for your .NET applications using Entity Framework.