initial commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
using Extrudex.Domain.Base;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace Extrudex.Infrastructure.Data.Configurations;
|
||||
|
||||
/// <summary>
|
||||
/// Base configuration for all entities. Sets up common conventions:
|
||||
/// - Table names in snake_case
|
||||
/// - GUID primary keys stored as PostgreSQL UUID
|
||||
/// - Automatic timestamp columns in snake_case
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">The entity type to configure.</typeparam>
|
||||
public abstract class BaseEntityConfiguration<TEntity> : IEntityTypeConfiguration<TEntity>
|
||||
where TEntity : BaseEntity
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<TEntity> builder)
|
||||
{
|
||||
// Table name in snake_case
|
||||
builder.ToTable(ToSnakeCase(typeof(TEntity).Name));
|
||||
|
||||
// Primary key stored as UUID
|
||||
builder.HasKey(e => e.Id);
|
||||
builder.Property(e => e.Id)
|
||||
.HasColumnName("id")
|
||||
.ValueGeneratedNever();
|
||||
|
||||
// If the entity is auditable, configure the timestamp columns
|
||||
if (typeof(AuditableEntity).IsAssignableFrom(typeof(TEntity)))
|
||||
{
|
||||
ConfigureAuditColumns(builder);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures audit timestamp columns (created_at, updated_at) for auditable entities.
|
||||
/// Uses string-based property names since the generic type constraint is BaseEntity
|
||||
/// and cannot be cast to AuditableEntity at compile time.
|
||||
/// </summary>
|
||||
private static void ConfigureAuditColumns(EntityTypeBuilder<TEntity> builder)
|
||||
{
|
||||
builder.Property<DateTime>("CreatedAt")
|
||||
.HasColumnName("created_at")
|
||||
.HasDefaultValueSql("now() at time zone 'utc'");
|
||||
|
||||
builder.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnName("updated_at")
|
||||
.HasDefaultValueSql("now() at time zone 'utc'");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts PascalCase or camelCase to snake_case.
|
||||
/// </summary>
|
||||
protected static string ToSnakeCase(string name)
|
||||
{
|
||||
return string.Concat(
|
||||
name.Select((ch, i) =>
|
||||
i > 0 && char.IsUpper(ch) && (char.IsLower(name[i - 1]) || (i + 1 < name.Length && char.IsLower(name[i + 1])))
|
||||
? "_" + ch
|
||||
: ch.ToString()))
|
||||
.ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user