.NET Core Postgres Context

I’ve been playing around with .NET recently to see if I like it as a strongly typed web framework. One issue I ran into though, was that the naming conventions with Entity Framework leverage pascal case. I appreciate that this closely matches the code, but I have been using Postgres for my database of choice lately and case-sensitive naming is a pain in that environment.

I found like-minded individuals discussing options in GitHub issues and blogs, and really appreciated the insights. So that I don’t have to count on finding those posts again, below is the DbContext I put together to convert naming conventions from pascal case to snake case. Along with converting to snake case, I also removed the asp_net_ prefix from the converted .NET Identity tables. This code is almost entirely copy-pasted from the other sources, so I’m not trying to take credit for it, really just documenting it for myself.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;

namespace App.Data
{
    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options): base(options)
        {
        }

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

            // Npgsql comes with a it's own translator, making conversion easy
            var mapper = new Npgsql.NameTranslation.NpgsqlSnakeCaseNameTranslator();

            foreach(var entity in builder.Model.GetEntityTypes())
            {
                entity.Relational().TableName = mapper.TranslateTypeName(entity.Relational().TableName);

                foreach(var property in entity.GetProperties())
                {
                    property.Relational().ColumnName = mapper.TranslateMemberName(property.Name);
                }

                foreach(var key in entity.GetKeys())
                {
                    key.Relational().Name = mapper.TranslateMemberName(key.Relational().Name);
                }

                foreach(var key in entity.GetForeignKeys())
                {
                    key.Relational().Name = mapper.TranslateMemberName(key.Relational().Name);
                }

                foreach(var index in entity.GetIndexes())
                {
                    index.Relational().Name = mapper.TranslateMemberName(index.Relational().Name);
                }

                // Drop the 'asp_net_' prefix from the Identity tables
                if (entity.Relational().TableName.StartsWith("asp_net_"))
                {
                    entity.Relational().TableName = entity.Relational().TableName.Replace("asp_net_", string.Empty);
                }
            }
        }
    }
}