Uncategorized

Hazina and Entity Framework Core: Database Patterns That Work

Hazina builds on top of Entity Framework Core, not around it. This means you keep all the EF Core features you know while getting Hazina’s additions for free. Here’s how they work together.

DbContext Setup

public class AppDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Order> Orders { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Apply Hazina conventions (soft delete filters, tenant filters, etc.)
        modelBuilder.ApplyHazinaConventions();
    }
}

Automatic Query Filters

When you call ApplyHazinaConventions(), EF Core global query filters are automatically configured:

  • Soft deleteWHERE IsDeleted = false on every query
  • Multi-tenantWHERE TenantId = @currentTenant on every query
  • OwnershipWHERE OwnerId = @currentUser for owned entities

Migrations

Standard EF Core migrations work as expected:

dotnet ef migrations add AddProducts
dotnet ef database update

Hazina adds automatic columns to your migrations:

  • CreatedAt and UpdatedAt – Set automatically on save
  • TenantId – Indexed for performance
  • IsDeleted – Indexed and included in query filter

Audit Trail

builder.Services.AddHazinaAudit<AppDbContext>(options => {
    options.TrackChanges = true;
    options.IncludePropertyValues = true;
    options.ExcludeEntities = new[] { typeof(AuditLog) }; // Don't audit the audit
});

Every create, update, and delete is logged with:

  • Who made the change
  • When it happened
  • What changed (old value to new value)
  • The entity type and ID

Repository Pattern

Hazina provides a generic repository that wraps common EF Core operations:

public interface IRepository<T> where T : EntityBase
{
    Task<T?> GetByIdAsync(int id);
    Task<PagedResult<T>> ListAsync(QueryOptions options);
    Task<T> CreateAsync(T entity);
    Task<T> UpdateAsync(T entity);
    Task DeleteAsync(int id);
    Task<int> CountAsync(FilterOptions? filter = null);
}

In the next post, we’ll explore production deployment – getting Hazina running in the real world.

Terug naar overzicht
ENNL