dotnet-ef-core-configuration
Generates Entity Framework Core configurations using Fluent API. Maps domain entities to database tables with proper relationships, constraints, and conventions.
git clone --depth 1 https://github.com/ronnythedev/dotnet-clean-architecture-skills /tmp/dotnet-ef-core-configuration && cp -r /tmp/dotnet-ef-core-configuration/skills/06-dotnet-ef-core-configuration ~/.claude/skills/dotnet-ef-core-configurationSKILL.md
# EF Core Configuration Generator
## Overview
This skill generates Entity Framework Core configurations using Fluent API:
- **IEntityTypeConfiguration<T>** - Per-entity configuration classes
- **Fluent API over attributes** - Keep domain clean
- **Snake case naming** - PostgreSQL convention
- **Relationships** - One-to-Many, Many-to-Many, One-to-One
- **Value Objects** - Owned types mapping
## Quick Reference
| Configuration | Use |
|---------------|-----|
| `ToTable()` | Table name |
| `HasKey()` | Primary key |
| `Property()` | Column configuration |
| `HasOne/HasMany()` | Relationships |
| `OwnsOne()` | Value objects |
| `HasIndex()` | Database indexes |
---
## Configuration Structure
```
/Infrastructure/Configurations/
├── {Entity}Configuration.cs
├── {ChildEntity}Configuration.cs
├── {ValueObject}Configuration.cs
└── OutboxMessageConfiguration.cs
```
---
## Template: Basic Entity Configuration
```csharp
// src/{name}.infrastructure/Configurations/{Entity}Configuration.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using {name}.domain.{aggregate};
namespace {name}.infrastructure.configurations;
internal sealed class {Entity}Configuration : IEntityTypeConfiguration<{Entity}>
{
public void Configure(EntityTypeBuilder<{Entity}> builder)
{
// ═══════════════════════════════════════════════════════════════
// TABLE MAPPING
// ═══════════════════════════════════════════════════════════════
builder.ToTable("{entity}"); // snake_case table name
// ═══════════════════════════════════════════════════════════════
// PRIMARY KEY
// ═══════════════════════════════════════════════════════════════
builder.HasKey(e => e.Id);
builder.Property(e => e.Id)
.ValueGeneratedNever(); // App generates GUIDs
// ═══════════════════════════════════════════════════════════════
// PROPERTIES
// ═══════════════════════════════════════════════════════════════
builder.Property(e => e.Name)
.HasMaxLength(100)
.IsRequired();
builder.Property(e => e.Description)
.HasColumnType("text"); // Unlimited length
builder.Property(e => e.IsActive)
.HasDefaultValue(true)
.IsRequired();
builder.Property(e => e.CreatedAt)
.IsRequired()
.HasDefaultValueSql("CURRENT_TIMESTAMP AT TIME ZONE 'UTC'");
builder.Property(e => e.UpdatedAt)
.IsRequired()
.HasDefaultValueSql("CURRENT_TIMESTAMP AT TIME ZONE 'UTC'");
// ═══════════════════════════════════════════════════════════════
// INDEXES
// ═══════════════════════════════════════════════════════════════
builder.HasIndex(e => e.Name)
.IsUnique();
builder.HasIndex(e => e.OrganizationId);
builder.HasIndex(e => new { e.OrganizationId, e.Name })
.IsUnique();
}
}
```
---
## Template: Entity with Relationships
```csharp
// src/{name}.infrastructure/Configurations/{Entity}Configuration.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using {name}.domain.{aggregate};
namespace {name}.infrastructure.configurations;
internal sealed class {Entity}Configuration : IEntityTypeConfiguration<{Entity}>
{
public void Configure(EntityTypeBuilder<{Entity}> builder)
{
builder.ToTable("{entity}");
builder.HasKey(e => e.Id);
// ═══════════════════════════════════════════════════════════════
// FOREIGN KEY PROPERTIES
// ═══════════════════════════════════════════════════════════════
builder.Property(e => e.OrganizationId)
.IsRequired();
builder.Property(e => e.ParentId); // Nullable FK
// ═══════════════════════════════════════════════════════════════
// ONE-TO-MANY: Parent has many children
// ═══════════════════════════════════════════════════════════════
builder.HasMany(e => e.{ChildEntities})
.WithOne(c => c.{Entity})
.HasForeignKey(c => c.{Entity}Id)
.OnDelete(DeleteBehavior.Cascade);
// ═══════════════════════════════════════════════════════════════
// MANY-TO-ONE: Entity belongs to Organization
// ═══════════════════════════════════════════════════════════════
builder.HasOne(e => e.Organization)
.WithMany(o => o.{Entities})
.HasForeignKey(e => e.OrganizationId)
.OnDelete(DeleteBehavior.Restrict); // Prevent cascade delete
// ═══════════════════════════════════════════════════════════════
// SELF-REFERENCING: Entity has optional parent
// ═══════════════════════════════════════════════════════════════
builder.HasOne(e => e.Parent)
.WithMany(e => e.Children)
.HasForeignKey(e => e.ParentId)
.OnDelete(DeleteBehavior.Restrict)
.IsRequired(false);
}
}
```
---
## Template: Child Entity Configuration
```csharp
// src/{name}.infrastructure/Configurations/{ChildEntity}Configuration.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using {name}.domain.{aggregate};
namespace {name}.infrastructure.configurations;
internal sealed class {ChildEntity}Configuration : IEntityTypeConfiguration<{ChildEntity}>
{
public void Configure(EntityTypeBuilder<{ChildEntity}> builder)
{
builder.ToTable("{child_entity}");
builder.HasKey(c => c.Id);
builder.Property(c => c.Id)
.ValueGeneratedNever();
builder.Property(c => c.{Parent}Id)
.IsRequired();
builder.Property(c => c.Name)
.HasMaxLength(100)
.IsRequired();
builder.Property(c => c.SortOrder)
.IsRequired()
.HasDefaultValue(0);Scaffolds a complete .NET solution following Clean Architecture principles with proper layer separation (API, Application, Domain, Infrastructure). Creates project structure, dependency injection setup, and cross-cutting concerns configuration.
Generates CQRS Commands with Handlers, Validators, and Request DTOs following Clean Architecture patterns. Commands represent actions that modify state and return Result types for proper error handling.
Generates CQRS Queries with Handlers and Response DTOs for read operations. Uses Dapper for optimized read queries, bypassing the domain model for better performance.
Generates Domain Entities following DDD principles with factory methods, private setters, domain events, and proper encapsulation. Supports aggregate roots, child entities, and value objects.
Generates Repository interfaces and implementations following the Repository pattern. Provides data access abstraction for aggregate roots with EF Core implementations.
Generates RESTful API Controllers with proper routing, versioning, authorization, and MediatR integration. Follows REST conventions and Clean Architecture patterns.
Generates Minimal API endpoints following Microsoft's recommended approach. Creates fast, testable HTTP APIs with minimal code using MapGet/MapPost/MapPut/MapDelete. Preferred over controller-based APIs for new projects.
Implements the Result pattern for explicit error handling without exceptions. Provides Result, Result<T>, and Error types for clean, predictable control flow in domain-driven applications.