npgsql / efcore.pg

Entity Framework Core provider for PostgreSQL
PostgreSQL License
1.52k stars 223 forks source link

SnakeCase .ToJson() columns #2998

Open c5racing opened 9 months ago

c5racing commented 9 months ago

Prior to .NET8, we decorated our entity property with [Column(TypeName = "jsonb")], which has not been deprecated for .NET's .ToJson() method.

We use all snake case tables and columns and could easily call our method to set these during the OnModelCreating event.

public static void SetTableNameAsSingularSnakeCase(this ModelBuilder modelBuilder)
{
    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    {
         entityType.SetTableName(entityType.GetDefaultTableName().ToSnakeCase());

         foreach (var property in entityType.GetProperties())
         {
             property.SetColumnName(property.GetDefaultColumnName().ToSnakeCase());
         }
    }
}

Now with the .ToJson(), this no longer works and our JSONB Columns are in the same case as our model. I understand we can override .ToJson such as the following:

    modelBuilder.Entity<Customer>()
        .OwnsOne(c => c.Details, d =>
        {
            d.ToJson("details");
            d.OwnsMany(d => d.Orders);
        });

however, this is a manual process. Is there any way to set these column names automagically during the model building method?

roji commented 9 months ago

I'm a bit confused... Your code sample above should work for normal tables and columns, but shouldn't be working for the traditional (pre-8.0 non-ToJson()) support for JSON; when you use [Column(TypeName = "jsonb")], we just hand the object off to System.Text.Json for serialization, and EF's model configuration (with SetColumnName etc.) has no effect on that.

In general, what you're looking for is EFCore.NamingConventions - that's an EF plugin specifically for applying naming conventions on your EF model. Version 8.0.0 currently isn't out and there are some issues with support of properties inside ToJson(), but this is something I plan to fix in the next couple of weeks for the 8.0.0 release. So I'd recommend waiting for that.

Otherwise, I need to see a minimal, runnable code sample showing what doesn't work.