using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; 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;