entity-framework-core

v2026.09.24

Entity Framework Core with DbContext, migrations, LINQ queries, relationships, and performance optimization. Covers EF Core 8+ patterns. USE WHEN: user mentions "Entity Framework", "EF Core", "DbContext", "migrations", "LINQ", "EF relationships", "database first", "code first" DO NOT USE FOR: Prisma - use `prisma`, Drizzle - use `drizzle`, Spring Data JPA - use `spring-data-jpa`, Dapper (raw SQL)

GitHub
安装命令
npx skhub add claude-dev-suite/entity-framework-core
Markdown
SKILL.md

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
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

MIT

源路径

skills/orm-odm/entity-framework-core

默认分支

main

最新提交

9496306

Tree SHA

fe4e2f1