mcpField
E
entity-framework-core

entity-framework-core

github.com/claude-dev-suiteDevelopment4665 installsUpdated 4d ago
Repository

About entity-framework-core

An Entity Framework Core quick-reference skill for .NET developers, covering DbContext, entity configuration, migrations, and LINQ queries. It also outlines query performance practices and troubleshooting.

Key features

  1. 01DbContext setup
  2. 02Fluent API entity configuration
  3. 03Database migration commands
  4. 04LINQ queries and projections
  5. 05Read-only and batch-operation tuning
  6. 06Troubleshooting common issues

Use cases

  1. 01Configure a database context and entities
  2. 02Run migrations to update a database
  3. 03Tune read-only queries and batch operations

MCP support

It mentions `mcp__documentation__fetch_docs` for retrieving in-depth Entity Framework Core documentation.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill entity-framework-core

After installing, type/entity-framework-corein Claude Code to confirm it loaded.

Details

From the project README

Entity Framework Core - Quick Reference

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: entity-framework-core for comprehensive documentation.

DbContext Setup

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    public DbSet<User> Users => Set<User>();
    public DbSet<Order> Orders => Set<Order>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
    }
}

// Registration
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

Entity Configuration (Fluent API)

public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.HasKey(u => u.Id);
        builder.Property(u => u.Name).IsRequired().HasMaxLength(100);
        builder.Property(u => u.Email).IsRequired().HasMaxLength(255);
        builder.HasIndex(u => u.Email).IsUnique();

        // Relationships
        builder.HasMany(u => u.Orders)
            .WithOne(o => o.User)
            .HasForeignKey(o => o.UserId)
            .OnDelete(DeleteBehavior.Cascade);

        // Value conversion
        builder.Property(u => u.Status)
            .HasConversion<string>();

        // Default values
        builder.Property(u => u.CreatedAt)
            .HasDefaultValueSql("GETUTCDATE()");
    }
}

Migrations

# Add migration
dotnet ef migrations add InitialCreate

# Update database
dotnet ef database update

# Remove last migration (not applied)
dotnet ef migrations remove

# Generate SQL script
dotnet ef migrations script

# Revert to specific migration
dotnet ef database update MigrationName

LINQ Queries

// Basic queries
var user = await context.Users.FindAsync(id);
var users = await context.Users.Where(u => u.IsActive).ToListAsync();
var user = await context.Users.FirstOrDefaultAsync(u => u.Email == email);

// Projection
var dtos = await context.Users
    .Where(u => u.IsActive)
    .Select(u => new UserResponse(u.Id, u.Name, u.Email))
    .ToListAsync();

// Include related data
var usersWithOrders = await context.Users
    .Include(u => u.Orders)
    .ThenInclude(o => o.OrderItems)
    .ToListAsync();

// Pagination
var page = await context.Users
    .OrderBy(u => u.Name)
    .Skip((pageNumber - 1) * pageSize)
    .Take(pageSize)
    .ToListAsync();

// Aggregation
var count = await context.Users.CountAsync(u => u.IsActive);
var avgAge = await context.Users.AverageAsync(u => u.Age);

Repository Pattern

public interface IRepository<T> where T : class
{
    Task<T?> GetByIdAsync(int id);
    Task<IEnumerable<T>> GetAllAsync();
    Task AddAsync(T entity);
    void Update(T entity);
    void Remove(T entity);
    Task<bool> ExistsAsync(Expression<Func<T, bool>> predicate);
    Task SaveChangesAsync();
}

public class Repository<T> : IRepository<T> where T : class
{
    protected readonly AppDbContext _context;
    protected readonly DbSet<T> _dbSet;

    public Repository(AppDbContext context)
    {
        _context = context;
        _dbSet = context.Set<T>();
    }

    public async Task<T?> GetByIdAsync(int id) => await _dbSet.FindAsync(id);
    public async Task<IEnumerable<T>> GetAllAsync() => await _dbSet.ToListAsync();
    public async Task AddAsync(T entity) => await _dbSet.AddAsync(entity);
    public void Update(T entity) => _dbSet.Update(entity);
    public void Remove(T entity) => _dbSet.Remove(entity);
    public async Task<bool> ExistsAsync(Expression<Func<T, bool>> predicate)
        => await _dbSet.AnyAsync(predicate);
    public async Task SaveChangesAsync() => await _context.SaveChangesAsync();
}

Performance Tips

TipImplementation
Use AsNoTracking() for read-onlycontext.Users.AsNoTracking().ToListAsync()
Use Select to projectAvoid loading full entities
Use AsSplitQuery()Prevent cartesian explosion with includes
Use compiled queriesEF.CompileAsyncQuery(...) for hot paths
Batch operationsExecuteUpdateAsync / ExecuteDeleteAsync (EF Core 7+)
// Bulk update (EF Core 7+)
await context.Users
    .Where(u => u.LastLoginAt < cutoff)
    .ExecuteUpdateAsync(u => u.SetProperty(x => x.IsActive, false));

// Bulk delete
await context.Users
    .Where(u => u.IsDeleted)
    .ExecuteDeleteAsync();

Anti-Patterns

Anti-PatternWhy It's BadCorrect Approach
Loading full entities for displayMemory waste, slowUse Select projections
N+1 queriesPerformance killerUse Include or projections
Not using AsNoTrackingUnnecessary overheadUse for read-only queries
Calling SaveChanges per entitySlow batch operationsCall once after all changes
Using DbContext as singletonThread-safety issuesUse AddDbContext (Scoped)

Quick Troubleshooting

IssueLikely CauseSolution
Tracking conflictEntity already trackedUse AsNoTracking or detach
Migration failsModel mismatchCheck pending changes, rebuild
Slow queryMissing indexAdd HasIndex in configuration
Lazy loading failsNot configuredUse Include (explicit loading)
Concurrency conflictStale dataAdd [ConcurrencyCheck] or RowVersion

Comments

Markdown supported