askill
database

databaseSafety --Repository

Efficient database operations with PostgreSQL, Entity Framework Core, migrations, indexing strategies, transactions, and connection pooling.

0 stars
1.2k downloads
Updated 2/3/2026

Package Files

Loading files...
SKILL.md

Database

Purpose: Efficient, reliable database operations with migrations, indexes, and transactions.
Stack: PostgreSQL + Entity Framework Core + Npgsql.


Entity Framework Core Setup

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(
        builder.Configuration.GetConnectionString("Default"),
        npgsqlOptions =>
        {
            npgsqlOptions.EnableRetryOnFailure(maxRetryCount: 3);
            npgsqlOptions.CommandTimeout(30);
        }));

Migrations

# Create migration
dotnet ef migrations add InitialCreate

# Update database
dotnet ef database update

# Generate SQL script
dotnet ef migrations script --output migration.sql

# Rollback
dotnet ef database update PreviousMigration

Migration Example

public partial class CreateUsersTable : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Users",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("Npgsql:ValueGenerationStrategy", 
                        NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
                Email = table.Column<string>(maxLength: 255, nullable: false),
                Name = table.Column<string>(maxLength: 100, nullable: false),
                CreatedAt = table.Column<DateTime>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Users", x => x.Id);
            });
        
        migrationBuilder.CreateIndex(
            name: "IX_Users_Email",
            table: "Users",
            column: "Email",
            unique: true);
    }
    
    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(name: "Users");
    }
}

Indexes

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // Single column index
    modelBuilder.Entity<User>()
        .HasIndex(u => u.Email)
        .IsUnique();
    
    // Composite index
    modelBuilder.Entity<Post>()
        .HasIndex(p => new { p.UserId, p.CreatedAt });
    
    // Filtered index
    modelBuilder.Entity<Order>()
        .HasIndex(o => o.Status)
        .HasFilter("Status = 'Active'");
}

When to Add Indexes:

  • Foreign keys
  • Columns in WHERE clauses
  • Columns in JOIN conditions
  • Columns in ORDER BY
  • Unique constraints

Transactions

using var transaction = await _context.Database.BeginTransactionAsync();
try
{
    var user = new User { Email = "test@example.com" };
    _context.Users.Add(user);
    await _context.SaveChangesAsync();
    
    var profile = new Profile { UserId = user.Id };
    _context.Profiles.Add(profile);
    await _context.SaveChangesAsync();
    
    await transaction.CommitAsync();
}
catch
{
    await transaction.RollbackAsync();
    throw;
}

Connection Pooling

// Connection string with pooling
"Server=localhost;Database=myapp;User Id=user;Password=pass;Pooling=true;MinPoolSize=0;MaxPoolSize=100;"

Query Optimization

Use Projections

// ❌ Loads entire entity
var users = await _context.Users.ToListAsync();

// ✅ Load only needed fields
var users = await _context.Users
    .Select(u => new { u.Id, u.Name, u.Email })
    .ToListAsync();

Avoid N+1 Queries

// ❌ N+1 queries
var users = await _context.Users.ToListAsync();
foreach (var user in users)
{
    var posts = await _context.Posts.Where(p => p.UserId == user.Id).ToListAsync();
}

// ✅ Eager loading
var users = await _context.Users
    .Include(u => u.Posts)
    .ToListAsync();

Use AsNoTracking

// For read-only queries
var users = await _context.Users
    .AsNoTracking()
    .ToListAsync();

Repository Pattern

public interface IRepository<T> where T : class
{
    Task<T?> GetByIdAsync(int id);
    Task<IEnumerable<T>> GetAllAsync();
    Task<T> AddAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(int id);
}

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<T> AddAsync(T entity)
    {
        await _dbSet.AddAsync(entity);
        await _context.SaveChangesAsync();
        return entity;
    }
}

Best Practices

✅ DO

  • Use migrations - Version control database schema
  • Add indexes - On foreign keys and WHERE clauses
  • Use transactions - For multi-step operations
  • Enable connection pooling - Reuse connections
  • Use AsNoTracking - For read-only queries
  • Use projections - Select only needed fields
  • Eager load related data - Avoid N+1 queries
  • Set command timeouts - Prevent hanging queries
  • Use parameterized queries - Always (prevent SQL injection)
  • Backup regularly - Automated backups

❌ DON'T

  • Load entire tables - Use pagination
  • Track read-only entities - Use AsNoTracking
  • Ignore N+1 queries - Profile and fix
  • Skip transactions - For multi-step operations
  • Hardcode connection strings - Use configuration
  • Create connections per query - Use pooling
  • Forget to dispose - Use using statements
  • Skip indexes - Profile and add as needed

Checklist

  • Migrations created and tested
  • Indexes on foreign keys and WHERE clauses
  • Connection pooling enabled
  • Transactions used for multi-step operations
  • N+1 queries eliminated
  • AsNoTracking for read-only queries
  • Projections used (select specific fields)
  • Command timeouts configured
  • Backup strategy in place
  • Connection strings externalized

See Also: 05-performance.md07-scalability.md

Last Updated: January 13, 2026

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

AI review pending.

Metadata

Licenseunknown
Version-
Updated2/3/2026
PublisherjnPiyush

Tags

databasetesting