Asp-Net-Core開發筆記:EFCore統一實體和屬性命名風格

程式設計實驗室發表於2023-10-09

前言

C# 編碼規範中,類和屬性都是大寫駝峰命名風格(PascalCase / UpperCamelCase),而在資料庫中我們往往使用小寫蛇形命名(snake_case),在預設情況下,EFCore會把原始的類名和屬性名直接對映到資料庫,這不符合資料庫的命名規範。

為了符合命名規範,而且也為了看起來更舒服,需要自己做命名轉換處理。

FreeSQL的命名轉換功能

FreeSQL 內建了很方便的命名風格轉換功能,只需要設定 UseNameConvert 就可以實現 Pasca Case 到 snake_case 的轉換。

var fsql = new FreeSqlBuilder()
  .UseConnectionString(DataType.MySql, Default.Value)
  .UseAutoSyncStructure(true)
  .UseNameConvert(NameConvertType.PascalCaseToUnderscoreWithLower)
  .UseMonitorCommand(cmd => Trace.WriteLine(cmd.CommandText))
  .Build();

EFCore 沒有內建這個功能,需要我們自行實現。

使用正則實現命名風格轉換

使用正規表示式可以實現這個功能

這裡來寫一個擴充套件方法

public static class StringExt {
    public static string ToSnakeCase(this string input) {
        if (string.IsNullOrEmpty(input)) {
            return input;
        }

        var startUnderscores = Regex.Match(input, @"^_+");
        return startUnderscores + Regex.Replace(input, @"([a-z0-9])([A-Z])", "$1_$2").ToLower();
    }
}

這個方法會在每個小寫字母/數字與大寫字母之間新增下劃線,並把整個字串轉換為小寫。

修改 EFCore 行為

EFCore 有非常豐富的功能,修改表名和欄位名當然也不在話下。

重寫 DbContextOnModelCreating 方法就行

public class AppDbContext : DbContext {
  // ...

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

    // CamelCase to SnakeCase
    foreach (var entity in modelBuilder.Model.GetEntityTypes()) {
      // Replace table names
      if (!string.IsNullOrWhiteSpace(entity.GetTableName())) {
        entity.SetTableName(entity.GetTableName()!.ToSnakeCase());
      }

      // Replace column names            
      foreach (var property in entity.GetProperties()) {
        property.SetColumnName(property.GetColumnName().ToSnakeCase());
      }

      foreach (var key in entity.GetKeys()) {
        if (!string.IsNullOrWhiteSpace(key.GetName())) {
          key.SetName(key.GetName()!.ToSnakeCase());
        }
      }

      foreach (var key in entity.GetForeignKeys()) {
        if (!string.IsNullOrWhiteSpace(key.GetConstraintName())) {
          key.SetConstraintName(key.GetConstraintName()!.ToSnakeCase());
        }
      }

      foreach (var index in entity.GetIndexes()) {
        if (!string.IsNullOrWhiteSpace(index.GetDatabaseName())) {
          index.SetDatabaseName(index.GetDatabaseName()!.ToSnakeCase());
        }
      }
    }
  }
}

以上程式碼會對錶名、列名、key、index的名稱做轉換。

搞定~

參考資料

相關文章