using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Tiku.Infrastructure.Persistence; internal static class ModelBuilderExtensions { public static void UseSnakeCaseIdentifiers(this ModelBuilder modelBuilder) { foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { foreach (var property in entityType.GetProperties()) property.SetColumnName(ToSnakeCase(property.Name)); foreach (var key in entityType.GetKeys()) if (key.GetName() is { } keyName) key.SetName(ToSnakeCase(keyName)); foreach (var foreignKey in entityType.GetForeignKeys()) if (foreignKey.GetConstraintName() is { } constraintName) foreignKey.SetConstraintName(ToSnakeCase(constraintName)); foreach (var index in entityType.GetIndexes()) if (index.GetDatabaseName() is { } indexName) index.SetDatabaseName(ToSnakeCase(indexName)); } } public static string ToSnakeCase(string value) { if (string.IsNullOrWhiteSpace(value)) return value; var builder = new StringBuilder(value.Length + 8); for (var index = 0; index < value.Length; index++) { var character = value[index]; if (char.IsUpper(character) && index > 0 && (char.IsLower(value[index - 1]) || (index + 1 < value.Length && char.IsLower(value[index + 1])))) builder.Append('_'); builder.Append(char.ToLowerInvariant(character)); } return builder.ToString(); } } internal sealed class SnakeCaseEnumConverter() : ValueConverter( value => ModelBuilderExtensions.ToSnakeCase(value.ToString()), value => Enum.Parse(value.Replace("_", string.Empty), true)) where TEnum : struct, Enum;