plugins/dotnet-blazor/skills/entity-framework/SKILL.md
Entity Framework Core patterns for data access, migrations, relationships, performance, and best practices
npx skillsauth add markus41/claude entity-frameworkInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
public sealed class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
{
public DbSet<Product> Products => Set<Product>();
public DbSet<Order> Orders => Set<Order>();
public DbSet<Customer> Customers => Set<Customer>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
}
}
public sealed class ProductConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.HasKey(p => p.Id);
builder.Property(p => p.Name).HasMaxLength(200).IsRequired();
builder.Property(p => p.Price).HasPrecision(18, 2);
builder.Property(p => p.Sku).HasMaxLength(50);
builder.HasIndex(p => p.Sku).IsUnique();
builder.HasOne(p => p.Category)
.WithMany(c => c.Products)
.HasForeignKey(p => p.CategoryId)
.OnDelete(DeleteBehavior.Restrict);
builder.HasMany(p => p.Tags)
.WithMany(t => t.Products)
.UsingEntity(j => j.ToTable("ProductTags"));
}
}
# Add migration
dotnet ef migrations add InitialCreate --project Data --startup-project Web
# Update database
dotnet ef database update --project Data --startup-project Web
# Generate SQL script
dotnet ef migrations script --idempotent --project Data --startup-project Web
# Remove last migration (if not applied)
dotnet ef migrations remove --project Data --startup-project Web
// Read (always use async, use AsNoTracking for reads)
var products = await db.Products
.AsNoTracking()
.Where(p => p.IsActive)
.OrderBy(p => p.Name)
.ToListAsync(ct);
// Read with projection (best performance)
var dtos = await db.Products
.AsNoTracking()
.Where(p => p.IsActive)
.Select(p => new ProductDto(p.Id, p.Name, p.Price))
.ToListAsync(ct);
// Create
db.Products.Add(new Product { Name = "New", Price = 9.99m });
await db.SaveChangesAsync(ct);
// Update
var product = await db.Products.FindAsync([id], ct);
if (product is not null)
{
product.Price = newPrice;
await db.SaveChangesAsync(ct);
}
// Delete
var product = await db.Products.FindAsync([id], ct);
if (product is not null)
{
db.Products.Remove(product);
await db.SaveChangesAsync(ct);
}
var orders = await db.Orders
.Include(o => o.Customer)
.Include(o => o.Items)
.ThenInclude(i => i.Product)
.AsSplitQuery() // Prevents cartesian explosion
.ToListAsync(ct);
private static readonly Func<AppDbContext, int, CancellationToken, Task<Product?>> GetProductById =
EF.CompileAsyncQuery((AppDbContext db, int id, CancellationToken ct) =>
db.Products.FirstOrDefault(p => p.Id == id));
// Usage
var product = await GetProductById(db, id, ct);
// Bulk update without loading entities
await db.Products
.Where(p => p.CategoryId == oldCategoryId)
.ExecuteUpdateAsync(s => s.SetProperty(p => p.CategoryId, newCategoryId), ct);
// Bulk delete
await db.Products
.Where(p => p.IsDeleted && p.DeletedAt < cutoff)
.ExecuteDeleteAsync(ct);
AsNoTracking() for read-only queriesSelect() projection to only load needed columnsAsSplitQuery() for multiple includesExecuteUpdateAsync/ExecuteDeleteAsync for bulk operationsToList() before Where() (loads entire table)IQueryable in repositories, materialize in servicesdevelopment
Enhanced plan-authoring skill with Pre-Writing context gathering, task metadata, non-TDD templates, Red Flags, telemetry, and an automated plan linter. Use when you have a spec or requirements for a multi-step task, before touching code.
tools
Documentation intelligence engine with graph-based API docs, algorithm library, and drift detection
tools
Ultraplan cloud planning — kick off a plan in the cloud from your terminal, review and revise in the browser, then execute remotely or send back to CLI
tools
--- name: mcp description: Configure MCP servers for Claude Code — stdio vs HTTP, authentication, Tools/Resources/Prompts distinction, channels (CI webhook, mobile relay, Discord bridge, fakechat), and cost of always-loaded tools. Use this skill whenever adding an MCP server, debugging connection issues, choosing between MCP Tools vs Prompts vs Resources, installing channel servers, or managing .mcp.json. Triggers on: "MCP server", "mcp config", "add Obsidian MCP", "install context7", "channels"