Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lower case table and column names #21

Closed
SepiaGroup opened this issue Apr 23, 2016 · 9 comments
Closed

Lower case table and column names #21

SepiaGroup opened this issue Apr 23, 2016 · 9 comments

Comments

@SepiaGroup
Copy link

Is it possible to have a config setting to lower case table and column names?

adding double-quotes is more annoying than having a table name like aspnetusers.

@roji
Copy link
Member

roji commented Apr 23, 2016

Not really... that's not how EF6 really works.

You can still override names yourself with the fluent API (or with attributes) but the better way is have table and column names that exactly mirror your classes. If you're using EF6 in the first place you're not necessarily writing a lot of custom SQL (at least in theory), and if you are you need to bite the bullet and just add quotes...

@roji roji closed this as completed Apr 23, 2016
@Emill
Copy link

Emill commented Apr 23, 2016

I guess this was about the newer EF and not EF6?

@SepiaGroup
Copy link
Author

yes this was about EF Core not EF 6

i was just thinking along the lines of how you can camel-case property names when you serialize an object to JSON ( CamelCasePropertyNamesContractResolver() ). Even though the Json object names do not match the C# property names exactly it sure does make it a lot easier when using the Json object in javascript.

@roji
Copy link
Member

roji commented Apr 23, 2016

Sorry, my bad, did not look at the repo the issue was in!

In my opinion it's a valid request, but which belongs in EF Core rather than in the Npgsql EF Core behavior. The idea of pluggable schemes for mapping c# names to database entiries could make sense in contexts beyond PostgreSQL/Npgsql...

@SepiaGroup
Copy link
Author

SepiaGroup commented Apr 23, 2016

I was think that it may belong in EF Core. but not knowing the inner workings of EF and how it is implemented i started here for a few reasons. Not all DBs are case sensitive and you probably don't want to lowercase names that are overridden in the fluent API or attributes, your overriding the name for a reason.

but i can see your point that this should be in EF Core. i will create a request in their repo.

dotnet/efcore#5159

thanks for the feedback

@roji
Copy link
Member

roji commented Apr 24, 2016

No problem @SepiaGroup. I think this could have value beyond PostgreSQL; a developer could simply decide they want to have snake-case tables (my_class_name) and have EF Core do the mapping automatically. This isn't necessarily related to lowercase.

@AuthorProxy
Copy link

Current code convert tables, properties, keys and indexes to snake case for Postgre, you can use it as a base for your custom conventions:

using System;
using System.Text.RegularExpressions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Npgsql;

namespace Database.Customization
{
    public class PostgreDbContext : DbContext
    {
        private static readonly Regex _keysRegex = new Regex("^(PK|FK|IX)_", RegexOptions.Compiled);

        public PostgreDbContext(DbContextOptions options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            FixSnakeCaseNames(modelBuilder);
        }

        private void FixSnakeCaseNames(ModelBuilder modelBuilder)
        {
            var mapper = new NpgsqlSnakeCaseNameTranslator();
            foreach (var table in modelBuilder.Model.GetEntityTypes())
            {
                ConvertToSnake(mapper, table);
                foreach (var property in table.GetProperties())
                {
                    ConvertToSnake(mapper, property);
                }

                foreach (var primaryKey in table.GetKeys())
                {
                    ConvertToSnake(mapper, primaryKey);
                }

                foreach (var foreignKey in table.GetForeignKeys())
                {
                    ConvertToSnake(mapper, foreignKey);
                }

                foreach (var indexKey in table.GetIndexes())
                {
                    ConvertToSnake(mapper, indexKey);
                }
            }
        }

        private void ConvertToSnake(INpgsqlNameTranslator mapper, object entity)
        {
            switch (entity)
            {
                case IMutableEntityType table:
                    var relationalTable = table.Relational();
                    relationalTable.TableName = ConvertGeneralToSnake(mapper, relationalTable.TableName);
                    if (relationalTable.TableName.StartsWith("asp_net_"))
                    {
                        relationalTable.TableName = relationalTable.TableName.Replace("asp_net_", string.Empty);
                        relationalTable.Schema = "identity";
                    }

                    break;
                case IMutableProperty property:
                    property.Relational().ColumnName = ConvertGeneralToSnake(mapper, property.Relational().ColumnName);
                    break;
                case IMutableKey primaryKey:
                    primaryKey.Relational().Name = ConvertKeyToSnake(mapper, primaryKey.Relational().Name);
                    break;
                case IMutableForeignKey foreignKey:
                    foreignKey.Relational().Name = ConvertKeyToSnake(mapper, foreignKey.Relational().Name);
                    break;
                case IMutableIndex indexKey:
                    indexKey.Relational().Name = ConvertKeyToSnake(mapper, indexKey.Relational().Name);
                    break;
                default:
                    throw new NotImplementedException("Unexpected type was provided to snake case converter");
            }
        }

        private string ConvertKeyToSnake(INpgsqlNameTranslator mapper, string keyName) =>
            ConvertGeneralToSnake(mapper, _keysRegex.Replace(keyName, match => match.Value.ToLower()));

        private string ConvertGeneralToSnake(INpgsqlNameTranslator mapper, string entityName) =>
            mapper.TranslateMemberName(ModifyNameBeforeConvertion(mapper, entityName));

        protected virtual string ModifyNameBeforeConvertion(INpgsqlNameTranslator mapper, string entityName) => entityName;
    }
}

@williamdenton
Copy link
Contributor

Updated for EfCore 3 => dotnet/efcore#5159 (comment)

@roji
Copy link
Member

roji commented Aug 19, 2019

Please note also #933, which is about making a proper snake-case plugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants