Agent Skillsmanagedcode/dotnet-skills › entity-framework-core

entity-framework-core

GitHub

用于设计、调优和审查 .NET Entity Framework Core 数据访问层,涵盖模型配置、迁移、查询翻译、性能优化及生命周期管理。

catalog/Frameworks/Entity-Framework-Core/skills/entity-framework-core/SKILL.md managedcode/dotnet-skills

Trigger Scenarios

进行 DbContext、迁移或 EF 查询开发 审查数据加载、跟踪行为或事务处理 从 EF6 或自定义仓储迁移至 EF Core 优化缓慢的数据库查询

Install

npx skills add managedcode/dotnet-skills --skill entity-framework-core -g -y
More Options

Non-standard path

npx skills add https://github.com/managedcode/dotnet-skills/tree/main/catalog/Frameworks/Entity-Framework-Core/skills/entity-framework-core -g -y

Use without installing

npx skills use managedcode/dotnet-skills@entity-framework-core

指定 Agent (Claude Code)

npx skills add managedcode/dotnet-skills --skill entity-framework-core -a claude-code -g -y

安装 repo 全部 skill

npx skills add managedcode/dotnet-skills --all -g -y

预览 repo 内 skill

npx skills add managedcode/dotnet-skills --list

SKILL.md

Frontmatter
{
    "name": "entity-framework-core",
    "description": "Design, tune, or review EF Core data access with proper modeling, migrations, query translation, performance, and lifetime management for modern .NET applications. USE FOR: DbContext, migrations, model configuration, EF queries, tracking, loading, performance, transactions, and EF6 migration decisions. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.",
    "compatibility": "Requires EF Core 7+ (preferably 8\/9 for latest features)."
}

Entity Framework Core

Trigger On

  • working on DbContext, migrations, model configuration, or EF queries
  • reviewing tracking, loading, performance, or transaction behavior
  • porting data access from EF6 or custom repositories to EF Core
  • optimizing slow database queries

Documentation

References

  • patterns.md - Query patterns, tracking strategies, loading strategies, projections, compiled queries, pagination, and temporal tables
  • anti-patterns.md - Common EF Core mistakes including N+1 queries, large contexts, generic repositories, and missing indexes

Workflow

  1. Prefer EF Core for new development unless a documented gap requires Dapper or raw SQL
  2. Keep DbContext lifetime scoped — align with unit of work
  3. Review query translation — check generated SQL, avoid N+1
  4. Treat migrations as first-class — reviewable, not throwaway
  5. Be deliberate about provider behavior — cross-provider but not identical
  6. Validate with query inspection — not just in-memory mental model

Current Upstream Notes

  • EF Core v10.0.11 is a servicing release. It fixes Azure SQL compatibility-level 170 JSON translation so nested OPENJSON projections retain AS JSON, and keeps EF compatible with .NET 11 MemoryExtensions.Min/Max overload additions. Re-run provider-backed JSON queries and compile against the repository's selected target framework after upgrading.
  • The August 2026 EF Core vs EF6 comparison remains the first stop for migration decisions. EF Core is the active cross-platform stack, but EF6-only EDMX/ObjectContext-heavy code should not move without a feature inventory and database-backed equivalence tests.

DbContext Patterns

Basic Configuration

public class AppDbContext : DbContext
{
    public DbSet<Product> Products => Set<Product>();
    public DbSet<Order> Orders => Set<Order>();

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

// Entity Configuration (Fluent API)
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
    public void Configure(EntityTypeBuilder<Product> builder)
    {
        builder.HasKey(p => p.Id);
        builder.Property(p => p.Name).HasMaxLength(200).IsRequired();
        builder.HasIndex(p => p.Sku).IsUnique();
        builder.HasMany(p => p.OrderItems).WithOne(oi => oi.Product);
    }
}

Registration with DI

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(connectionString)
           .EnableSensitiveDataLogging()  // Dev only
           .EnableDetailedErrors());      // Dev only

// Or with pooling (better performance)
builder.Services.AddDbContextPool<AppDbContext>(options =>
    options.UseSqlServer(connectionString));

Query Patterns

Use AsNoTracking for Read-Only

// Bad - tracks entities unnecessarily
var products = await db.Products.ToListAsync();

// Good - no tracking overhead
var products = await db.Products
    .AsNoTracking()
    .ToListAsync();

Project to DTOs

// Bad - loads entire entity graph
var orders = await db.Orders
    .Include(o => o.Items)
    .Include(o => o.Customer)
    .ToListAsync();

// Good - loads only needed data
var orders = await db.Orders
    .Select(o => new OrderDto
    {
        Id = o.Id,
        CustomerName = o.Customer.Name,
        ItemCount = o.Items.Count,
        Total = o.Items.Sum(i => i.Price)
    })
    .ToListAsync();

Avoid N+1 Queries

// Bad - N+1 problem
foreach (var order in orders)
{
    var items = await db.OrderItems
        .Where(i => i.OrderId == order.Id)
        .ToListAsync();
}

// Good - eager loading
var orders = await db.Orders
    .Include(o => o.Items)
    .ToListAsync();

// Good - split query for large graphs
var orders = await db.Orders
    .Include(o => o.Items)
    .AsSplitQuery()
    .ToListAsync();

Compiled Queries (EF Core 9)

// Pre-compiled for frequently used queries
private static readonly Func<AppDbContext, int, Task<Product?>> GetProductById =
    EF.CompileAsyncQuery((AppDbContext db, int id) =>
        db.Products.FirstOrDefault(p => p.Id == id));

// Usage
var product = await GetProductById(db, productId);

Migration Patterns

Creating Migrations

# Add migration
dotnet ef migrations add AddProductIndex

# Apply to database
dotnet ef database update

# Generate SQL script
dotnet ef migrations script --idempotent -o migrate.sql

Data Migrations

public partial class AddProductIndex : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateIndex(
            name: "IX_Products_Sku",
            table: "Products",
            column: "Sku",
            unique: true);

        // Data migration (if needed)
        migrationBuilder.Sql(@"
            UPDATE Products
            SET NormalizedName = UPPER(Name)
            WHERE NormalizedName IS NULL");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropIndex(
            name: "IX_Products_Sku",
            table: "Products");
    }
}

Anti-Patterns to Avoid

Anti-Pattern Why It's Bad Better Approach
ToList() then filter Loads all data to memory Filter in query
Multiple DbContext per request Transaction issues Scoped lifetime
Lazy loading everywhere N+1 queries Explicit Include
Generic repository wrapper Removes query power Use DbContext directly
Ignoring generated SQL Hidden performance issues Log and review
SaveChanges() in loops Many roundtrips Batch then save

Performance Best Practices

  1. Index frequently queried columns:

    builder.HasIndex(p => p.CreatedAt);
    builder.HasIndex(p => new { p.Category, p.Status });
    
  2. Use pagination:

    var page = await db.Products
        .OrderBy(p => p.Id)
        .Skip(pageSize * pageNumber)
        .Take(pageSize)
        .ToListAsync();
    
  3. Batch updates (EF Core 7+):

    await db.Products
        .Where(p => p.Category == "Obsolete")
        .ExecuteDeleteAsync();
    
    await db.Products
        .Where(p => p.Category == "Sale")
        .ExecuteUpdateAsync(p => p.SetProperty(x => x.Price, x => x.Price * 0.9m));
    
  4. Minimize network roundtrips:

    // Bad - 3 roundtrips
    var product = await db.Products.FindAsync(id);
    var reviews = await db.Reviews.Where(r => r.ProductId == id).ToListAsync();
    var related = await db.Products.Where(p => p.Category == product.Category).ToListAsync();
    
    // Good - 1 roundtrip
    var data = await db.Products
        .Where(p => p.Id == id)
        .Select(p => new
        {
            Product = p,
            Reviews = p.Reviews,
            Related = db.Products.Where(r => r.Category == p.Category).Take(5)
        })
        .FirstOrDefaultAsync();
    

Concurrency Patterns

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }

    [ConcurrencyCheck]
    public int Version { get; set; }

    // Or use RowVersion
    [Timestamp]
    public byte[] RowVersion { get; set; }
}

// Handle concurrency conflicts
try
{
    await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
    var entry = ex.Entries.Single();
    var databaseValues = await entry.GetDatabaseValuesAsync();
    // Resolve conflict...
}

Deliver

  • EF Core models and queries that match the domain
  • safer migrations and lifetime management
  • performance-aware data access decisions
  • proper indexing and query optimization

Validate

  • query behavior is intentional (check SQL logs)
  • migrations are reviewable and correct
  • no N+1 queries in common paths
  • indexes exist for filtered/sorted columns
  • DbContext lifetime is scoped properly
  • concurrency is handled for critical entities

Version History

  • 0559476 Current 2026-08-19 23:31

    更新上游版本说明,修复 Azure SQL JSON 翻译兼容性问题,并适配 .NET 11 新重载方法。

  • 7ab7f03 2026-07-25 05:21

Same Skill Collection

catalog/Frameworks/gRPC/skills/grpc/SKILL.md
catalog/Frameworks/Official-Astro/skills/astro-developer/SKILL.md
catalog/Frameworks/Official-DotNet-ASPNetCore/skills/configuring-opentelemetry-dotnet/SKILL.md
catalog/Frameworks/Official-DotNet-ASPNetCore/skills/dotnet-webapi/SKILL.md
catalog/Frameworks/Official-DotNet-ASPNetCore/skills/minimal-api-file-upload/SKILL.md
catalog/Frameworks/Orleans/skills/orleans/SKILL.md
catalog/Frameworks/ThreeJS-WebGPU-TSL/skills/webgpu-threejs-tsl/SKILL.md
catalog/Libraries/Official-DotNet-Data/skills/optimizing-ef-core-queries/SKILL.md
catalog/Platform/Official-DotNet-Advanced/skills/csharp-scripts/SKILL.md
catalog/Platform/Official-DotNet-Advanced/skills/nuget-trusted-publishing/SKILL.md
catalog/Platform/Official-DotNet-Blazor/skills/create-blazor-project/SKILL.md
catalog/Platform/Official-DotNet-Blazor/skills/fetch-and-send-data/SKILL.md
catalog/Platform/Official-DotNet-Blazor/skills/support-prerendering/SKILL.md
catalog/Platform/Official-DotNet-Blazor/skills/use-js-interop/SKILL.md
catalog/Platform/Official-DotNet-Experimental/skills/exp-mock-usage-analysis/SKILL.md
catalog/Platform/Official-DotNet-Experimental/skills/exp-simd-vectorization/SKILL.md
catalog/Platform/Official-DotNet-Test-Migration/skills/migrate-xunit-to-mstest/SKILL.md
catalog/Platform/Official-DotNet-Test-Migration/skills/migrate-xunit-to-xunit-v3/SKILL.md
catalog/Platform/Official-DotNet-Upgrade/skills/dotnet-aot-compat/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/code-testing-extensions/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/filter-syntax/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/find-untested-sources/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/platform-detection/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/scaffold-dotnet-test-project/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/test-gap-analysis/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/testability-obstacle/SKILL.md
catalog/Testing/Playwright/skills/playwright-visual-testing/SKILL.md
catalog/Testing/xUnit/skills/xunit/SKILL.md
catalog/Tools/Code-Analysis/skills/code-analysis/SKILL.md
catalog/Tools/HTMLHint/skills/htmlhint/SKILL.md
catalog/Tools/Official-DotNet-Diagnostics/skills/analyzing-dotnet-performance/SKILL.md
catalog/Tools/Official-DotNet-Diagnostics/skills/clr-activation-debugging/SKILL.md
catalog/Tools/Official-DotNet-Diagnostics/skills/dotnet-trace-collect/SKILL.md
catalog/Tools/Official-DotNet-Diagnostics/skills/dump-collect/SKILL.md
catalog/Tools/Official-DotNet-MSBuild/skills/binlog-failure-analysis/SKILL.md
catalog/Tools/Official-DotNet-MSBuild/skills/copy-to-output-directory/SKILL.md
catalog/Tools/Official-DotNet-MSBuild/skills/msbuild-server/SKILL.md
catalog/Tools/Official-DotNet-MSBuild/skills/resolve-project-references/SKILL.md
catalog/Tools/ReportGenerator/skills/reportgenerator/SKILL.md
catalog/Tools/ReSharper-CLT/skills/resharper-clt/SKILL.md
catalog/Tools/Roslynator/skills/roslynator/SKILL.md
catalog/Tools/Stylelint/skills/stylelint/SKILL.md
external-sources/upstreams/webgpu-claude-skill/skills/webgpu-threejs-tsl/SKILL.md
catalog/Frameworks/ASP.NET-Core/skills/aspnet-core/SKILL.md
catalog/Frameworks/Aspire/skills/aspire/SKILL.md
catalog/Frameworks/Azure-Functions/skills/azure-functions/SKILL.md
catalog/Frameworks/Blazor/skills/blazor/SKILL.md
catalog/Frameworks/Entity-Framework-6/skills/entity-framework6/SKILL.md
catalog/Frameworks/MAUI/skills/maui/SKILL.md

Metadata

Files
0
Version
0559476
Hash
4def5773
Indexed
2026-07-25 05:21

inicio - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-20 06:02
浙ICP备14020137号-1 $mapa de visitantes$