home / skills / stuartf303 / sorcha / entity-framework

entity-framework skill

/.claude/skills/entity-framework

This skill helps you manage Entity Framework Core with PostgreSQL, enabling migrations, repositories, and optimized data access patterns.

npx playbooks add skill stuartf303/sorcha --skill entity-framework

Review the files below or copy the command above to add this skill to your agents.

Files (3)
SKILL.md
3.6 KB
---
name: entity-framework
description: |
  Handles Entity Framework Core database access, migrations, and repository patterns for PostgreSQL.
  Use when: Creating DbContext classes, writing migrations, implementing repositories, configuring entity relationships, or optimizing database queries.
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, mcp__context7__resolve-library-id, mcp__context7__query-docs
---

# Entity Framework Core Skill

Sorcha uses EF Core 9+ with PostgreSQL (Npgsql) as the primary relational data store. The codebase implements a layered repository pattern with generic and specialized repositories, soft delete via query filters, and automatic migrations on startup.

## Quick Start

### Register DbContext with PostgreSQL

```csharp
// src/Common/Sorcha.Storage.EFCore/Extensions/EFCoreServiceExtensions.cs
services.AddDbContext<WalletDbContext>((sp, options) =>
{
    var dataSource = sp.GetRequiredService<NpgsqlDataSource>();
    options.UseNpgsql(dataSource, npgsql =>
    {
        npgsql.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorCodesToAdd: null);
        npgsql.MigrationsHistoryTable("__EFMigrationsHistory", "wallet");
    });
});
```

### Create a Migration

```bash
# From project directory containing DbContext
dotnet ef migrations add InitialSchema --project src/Common/Sorcha.Wallet.Core --startup-project src/Services/Sorcha.Wallet.Service
```

### Apply Migrations Programmatically

```csharp
// Startup pattern used in Sorcha services
var pending = await dbContext.Database.GetPendingMigrationsAsync();
if (pending.Any())
    await dbContext.Database.MigrateAsync();
```

## Key Concepts

| Concept | Usage | Example |
|---------|-------|---------|
| DbContext | Schema definition + change tracking | `WalletDbContext`, `TenantDbContext` |
| Repository | Data access abstraction | `EFCoreRepository<T, TId, TContext>` |
| Soft Delete | Query filter on `DeletedAt` | `.HasQueryFilter(e => e.DeletedAt == null)` |
| JSONB | PostgreSQL JSON columns | `.HasColumnType("jsonb")` |
| ExecuteUpdate | Bulk updates without loading | `ExecuteUpdateAsync(s => s.SetProperty(...))` |

## Common Patterns

### Repository with Optional Eager Loading

```csharp
// src/Common/Sorcha.Wallet.Core/Repositories/EfCoreWalletRepository.cs
public async Task<WalletEntity?> GetByAddressAsync(string address, bool includeAddresses = false)
{
    IQueryable<WalletEntity> query = _context.Wallets;
    
    if (includeAddresses)
        query = query.Include(w => w.Addresses);
    
    return await query.AsNoTracking().FirstOrDefaultAsync(w => w.Address == address);
}
```

### Soft Delete with Filter Bypass

```csharp
// Bypass query filter for admin operations
var deleted = await _context.Wallets
    .IgnoreQueryFilters()
    .FirstOrDefaultAsync(w => w.Address == address);
```

## See Also

- [patterns](references/patterns.md) - DbContext configuration, entity mapping, query optimization
- [workflows](references/workflows.md) - Migration commands, testing patterns, deployment

## Related Skills

- See the **postgresql** skill for connection configuration and PostgreSQL-specific features
- See the **aspire** skill for service registration and health checks
- See the **xunit** skill for testing DbContext with InMemory provider

## Documentation Resources

> Fetch latest EF Core documentation with Context7.

**Library ID:** `/dotnet/entityframework.docs`

**Recommended Queries:**
- "DbContext pooling configuration dependency injection"
- "migrations code-first apply production deployment"
- "query filters soft delete global filters"
- "bulk operations ExecuteUpdate ExecuteDelete"

Overview

This skill provides Entity Framework Core patterns and helpers for PostgreSQL-backed applications, focusing on DbContext setup, migrations, repository abstractions, and query optimization. It documents recommended practices like soft delete query filters, JSONB mapping, bulk updates, and programmatic migration application. It is tailored for EF Core 9+ with Npgsql and layered repository designs.

How this skill works

It inspects and describes how to register DbContext with an Npgsql data source, configure retry policies, and set the migrations history schema. It explains creating and applying migrations, implementing generic and specialized repositories, and common query patterns such as eager loading, soft delete filters, and bulk ExecuteUpdate/ExecuteDelete operations. It also covers bypassing global filters for administrative operations and mapping JSONB columns.

When to use it

  • Creating or configuring DbContext classes for PostgreSQL
  • Authoring and applying code-first EF Core migrations
  • Implementing repository patterns (generic and specialized)
  • Defining entity relationships and query filters (soft delete)
  • Optimizing queries with bulk updates or no-tracking reads
  • Testing DbContext behavior and migration workflows

Best practices

  • Register DbContext with an NpgsqlDataSource and enable retry on failure for resilient connections
  • Keep migrations in the project containing the DbContext and run migrations from the service startup or CI/CD pipeline
  • Use AsNoTracking for read-only queries and Include only when needed to avoid over-fetching
  • Apply global HasQueryFilter for soft delete and use IgnoreQueryFilters for admin or restore operations
  • Map JSON payloads to jsonb columns for flexible schemas and use ExecuteUpdate/ExecuteDelete for bulk operations without loading entities

Example use cases

  • Register WalletDbContext with a scoped NpgsqlDataSource and configure migrations history in a dedicated schema
  • Add a new code-first migration then run dotnet ef migrations add from the DbContext project and apply via Database.MigrateAsync at startup
  • Implement EFCoreRepository<T, TId, TContext> for common CRUD and extend with specialized repositories for domain queries
  • Use AsNoTracking + FirstOrDefaultAsync for single-result reads and Include when eager loading related collections
  • Perform soft-delete by setting DeletedAt and relying on HasQueryFilter, use IgnoreQueryFilters for restore or audit queries
  • Run bulk status updates with ExecuteUpdateAsync to change multiple rows without materializing entities

FAQ

Where should I keep migrations?

Keep migrations in the project that contains the DbContext to ensure paths and namespaces align, and run ef commands from that project with the appropriate startup-project setting.

How do I run migrations automatically?

Check for pending migrations via Database.GetPendingMigrationsAsync and call Database.MigrateAsync during service startup or in your deployment script.

When should I bypass soft delete filters?

Bypass global filters for administrative tasks like restore, permanent delete, or audit queries where you must inspect historically deleted rows.