Skip to content
dotnet-efcore-guidelines logo

.NET + Entity Framework Core Guidelines

dotnet-efcore-guidelines

Entity Framework Core best practices for Clean Architecture projects. Covers DbContext, entity configurations, repository pattern, migrations, and PostgreSQL-specific features.

SKILL.md

Full skill instructions

.NET + Entity Framework Core Guidelines

Project-Agnostic EF Core Patterns

Placeholders use {Placeholder} syntax - see docs/​TEMPLATE_GLOSSARY.md.

Purpose

This skill provides comprehensive best practices for using Entity Framework Core with PostgreSQL in Clean Architecture projects. It details conventions for DbContext, entity configurations, repository patterns, migrations, and PostgreSQL-specific features.

When This Skill Activates

Triggered by:

  • Keywords: "ef core", "entity framework", "dbcontext", "repository", "migration", "database", "postgres", "postgresql"
  • File patterns: **/​Persistence/​**/​*.cs, **/​Repositories/​**/​*.cs, **/​*DbContext.cs, **/​Configurations/​**/​*.cs

EF Core Architecture

The persistence layer ({Project}.Persistence) is responsible for data access and storage. It implements interfaces defined in the Application layer, adhering to Clean Architecture principles.

graph TD
    subgraph Application Layer
        A[I{Entity}Repository] --> B[{Entity}]
        B[{Entity}] --> C[Domain Layer]
    end

    subgraph Persistence Layer
        D[{DbContext}] --> B
        E[{Entity}Repository] --> D
        E --> A
    end

    A -- Implemented by --> E
    C -- Used by --> B
    D -- Configures --> B

Resources

For more detailed examples, refer to the resources/ folder within this skill.

ResourceDescription
dbcontext-patterns.mdDbContext configuration, SaveChangesAsync override
entity-configuration.mdIEntityTypeConfiguration, TPT, PostgreSQL functions
repository-pattern.mdGenericRepository, custom repositories
querying-patterns.mdInclude, Select, projections, performance
migrations.mdCreating and applying migrations

Quick Reference

1. DbContext Pattern

The {DbContext} manages database interactions.

// File: {Project}.Persistence/​{DbContext}.cs
public class {DbContext} : DbContext
{
    public {DbContext}(DbContextOptions<{DbContext}> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        // Automatically applies all IEntityTypeConfiguration<T> from the assembly
        modelBuilder.ApplyConfigurationsFromAssembly(typeof({DbContext}).Assembly);
    }

    // Override SaveChangesAsync for cross-cutting concerns like auditing or soft deletes
    public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        // Example: Audit logging or automatic timestamp updates
        foreach (var entry in ChangeTracker.Entries())
        {
            // Handle CreatedAt, UpdatedAt logic
        }
        return base.SaveChangesAsync(cancellationToken);
    }

    public DbSet<{Entity}> {Entities} { get; set; } = null!;
    public DbSet<{ParentEntity}> {ParentEntities} { get; set; } = null!;
    // ... other DbSets
}

For more details, see dbcontext-patterns.md.

2. Entity Configuration

All entity-specific configurations are done using IEntityTypeConfiguration<T> in separate classes.

// File: {Project}.Persistence/​Configurations/​Entities/​{Entity}Configuration.cs
public class {Entity}Configuration : IEntityTypeConfiguration<{Entity}>
{
    public void Configure(EntityTypeBuilder<{Entity}> builder)
    {
        // Project Standard: Table Per Type (TPT) inheritance strategy
        builder.UseTptMappingStrategy();

        // Project Standard: UUIDv7 primary keys for main entities
        builder.Property(e => e.Id).HasDefaultValueSql("uuidv7()");

        // Database-level defaults are acceptable here, not in domain entities
        builder.Property(e => e.ViewCount).HasDefaultValue(0);

        builder.Property(e => e.Title).HasMaxLength(200).IsRequired();
        builder.Property(e => e.Description).HasMaxLength(5000);

        // Example relationship configuration
        builder.HasOne(e => e.{ParentEntity})
            .WithMany()
            .HasForeignKey(e => e.{ParentEntity}Id)
            .OnDelete(DeleteBehavior.Restrict);
    }
}

For more details, see entity-configuration.md.

3. Repository Pattern

Repositories abstract data access. Interfaces reside in the Application layer, and implementations are in the Persistence layer.

CRITICAL RULE: Repositories MUST return DOMAIN ENTITIES, not DTOs. DTO mapping always happens in the Application layer handlers via AutoMapper.

// File: {Project}.Application/​Contracts/​Persistence/​I{Entity}Repository.cs (Application Layer)
public interface I{Entity}Repository : IGenericRepository<{Entity}, {IdType}>
{
    Task<List<{Entity}>> Get{Entities}WithDetails(); // Returns List<{Entity}>
    Task<{Entity}?> Get{Entity}WithDetails({IdType} id); // Returns {Entity}?
}

// File: {Project}.Persistence/​Repositories/​{Entity}Repository.cs (Persistence Layer)
public class {Entity}Repository : GenericRepository<{Entity}, {IdType}>, I{Entity}Repository
{
    private readonly {DbContext} _dbContext;

    public {Entity}Repository({DbContext} dbContext) : base(dbContext) => _dbContext = dbContext;

    public async Task<List<{Entity}>> Get{Entities}WithDetails()
    {
        return await _dbContext.{Entities}
            .Include(e => e.{LookupEntity})
            .Include(e => e.{RelatedEntity1})
            .Include(e => e.{RelatedEntity2})
            .ToListAsync(); // Returns entities
    }
}

For more details, see repository-pattern.md.

4. Querying Patterns

Efficient querying is crucial for performance. Avoid N+1 issues by using eager loading (Include) and projections (Select).

// Example: Query with eager loading and projection to DTO (in Application Layer Handler)
public async Task<List<{Entity}ListDto>> Handle(Get{Entity}ListRequest request, CancellationToken cancellationToken)
{
    var {entities} = await _{entity}Repository.Get{Entities}WithDetails(); // Repository returns entities
    return _mapper.Map<List<{Entity}ListDto>>({entities}); // Handler maps to DTOs
}

// Example: Using AsNoTracking for read-only queries (in Repository)
public async Task<List<{Entity}>> Get{Entities}ReadOnly()
{
    return await _dbContext.{Entities}
        .AsNoTracking() // Disables change tracking for performance
        .Include(e => e.{ParentEntity})
        .ToListAsync();
}

For more details, see querying-patterns.md.

5. Migrations

Database schema changes are managed through EF Core migrations.

# Create a new migration for schema changes
dotnet ef migrations add AddNewFieldTo{Entity} --project {Project}.Persistence

# Apply pending migrations to the database
dotnet ef database update --project {Project}.Persistence

# Generate SQL script for production deployment
dotnet ef migrations script --idempotent --output migrations/​release.sql --project {Project}.Persistence

For more details, see migrations.md.

Key Principles & Conventions

  • IDs: All primary keys are Guid (or {IdType}), except for lookup tables which use int (or {LookupIdType}).
  • Numeric Types: Use int instead of long unless explicitly required for large values (e.g., file sizes, pagination cursors).
  • Default Values: DO NOT add default values in domain entity property initializers (e.g., public int ViewCount { get; set; } = 0;). Set defaults in application handlers or use database-level defaults via IEntityTypeConfiguration.
  • Link Tables: Navigation properties on link/​mapping tables are readonly for queries only. Writes must go through the link table's repository directly.
  • PostgreSQL Features: Leverage PostgreSQL-specific features like UUIDv7 for primary keys and PostGIS for spatial data handling.

Related Documentation:

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View