-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
pluggable schemes for mapping c# names #5159
Comments
Just to add a bit of detail, this would provide users the choice to map C# names like MyClassName to my_class_name, etc. |
Another note: the same mapping scheme provider would ideally be used for reverse-engineering. |
It's actually super easy to override the default naming scheme with some simple code in your foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entity.GetProperties())
{
property.Relational().ColumnName = property.Name.ToLower();
}
} Or I prefer to write it like this... modelBuilder.Model.GetEntityTypes()
.SelectMany(e => e.GetProperties())
.ToList()
.ForEach(p => p.Relational().ColumnName = p.Name.ToLower()); |
Of course... that makes total sense. |
modelBuilder does not seem to be in OnConfiguring but is in OnModelCreating, which is where i place this code. to lower table names i added // Lower Table Names // Lower column names thanks. |
Typo on my behalf, OnModelCreating is the correct place (I updated my original comment). |
How about lowercase of table names? Got it. Just sharing this here:
If there is a better way let me know |
@geocine Your solution uses the full namespace to generate the name which can lead to very long (and ugly) names for tables and keys/indices. Fortunately Npgsql already offers an SnakeCase-Translator (which it uses for enums) so I solved it like this:
}` called from here
|
@asymetrixs I did not know there was a built in function for snake case thank you For the table name, I am actually using the name of the DbSet when you add it to your context. Example: public DbSet<Employee> EmployeeDetails { get; set; } It will give you |
In my case, modelBuilder.Model is not available. in which name space the Model class is available? |
@FikruKebede Are you sure you are using EF Core, not EF6? |
I was using EF6. Now I am using EF Core and the problem is fixed. |
Hi!! Not working in my code, all tables and fields still in CamelCase. My context class is this: public class SevntDbContext : IdentityDbContext<Usuario, IdentityRoleSevnt, int>, ISevntDbContext
{
public SevntDbContext() : base()
{
Configure();
}
public SevntDbContext(DbContextOptions<SevntDbContext> options) : base(options)
{
Configure();
}
private void Configure()
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("project.json", optional: true)
.AddJsonFile("appsettings.json", optional: false);
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
public DbSet<Adjunto> Adjuntos { get; set; }
public DbSet<CategoriaEvento> CategoriasEvento { get; set; }
public DbSet<Provincia> Provincias { get; set; }
public DbSet<Pais> Paises { get; set; }
public DbSet<Empresa> Empresas { get; set; }
public DbSet<Usuario> Usuarios { get; set; }
public DbSet<TipoCondicionFiscal> TiposCondicionesFiscales { get; set; }
public DbSet<TipoDocumento> TiposDocumento { get; set; }
public DbSet<TipoEntrada> TipoEntrada { get; set; }
public DbSet<TipoEstadoCivil> TiposEstadoCivil { get; set; }
public DbSet<Entrada> Entradas { get; set; }
public DbSet<Evento> Eventos { get; set; }
public DbSet<Zona> Zonas { get; set; }
public DbSet<Pedido> Pedidos { get; set; }
public DbSet<TipoAlerta> TiposAlerta { get; set; }
public DbSet<Ingreso> Ingresos { get; set; }
public DbSet<Persona> Personas { get; set; }
public DbSet<PersonaVinculo> PersonasVinculos { get; set; }
public DbSet<PersonaAlertaCargada> PersonasAlertasCargadas { get; set; }
public DbSet<PersonaAlertaEmitida> PersonasAlertasEmitidas { get; set; }
public DbSet<TipoUsuario> TiposUsuario { get; set; }
public DbSet<Horario> Horarios { get; set; }
public DbSet<DiaSemana> DiasSemana { get; set; }
public DbSet<BoardingPass> BoardingPasses { get; set; }
public DbSet<Aerolinea> Aerolineas { get; set; }
public DbSet<IATAAeropuerto> IATAAeropuertos { get; set; }
public DbSet<IATAPais> IATAPaises { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql(Configuration["ConnectionStrings:ConnectionString"]); //.MigrationsAssembly("pBoxe.DataAccess"); // optionsBuilder.UseSqlServer("Server=localhost;Database=Sevnt;Trusted_Connection=True;MultipleActiveResultSets=true;"); //.MigrationsAssembly("pBoxe.DataAccess");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasPostgresExtension("citext");
new AdjuntoMap(modelBuilder.Entity<Adjunto>());
new CategoriaEventoMap(modelBuilder.Entity<CategoriaEvento>());
new EmpresaMap(modelBuilder.Entity<Empresa>());
new EntradaMap(modelBuilder.Entity<Entrada>());
new EventoMap(modelBuilder.Entity<Evento>());
new ProvinciaMap(modelBuilder.Entity<Provincia>());
new PaisMap(modelBuilder.Entity<Pais>());
new TipoDocumentoMap(modelBuilder.Entity<TipoDocumento>());
new TipoEntradaMap(modelBuilder.Entity<TipoEntrada>());
new TipoCondicionFiscalMap(modelBuilder.Entity<TipoCondicionFiscal>());
new TipoEstadoCivilMap(modelBuilder.Entity<TipoEstadoCivil>());
new UsuarioMap(modelBuilder.Entity<Usuario>());
new PedidoMap(modelBuilder.Entity<Pedido>());
new UsuarioEventoMap(modelBuilder.Entity<UsuarioEvento>());
new UsuarioEventoFavoritosMap(modelBuilder.Entity<UsuarioEventoFavoritos>());
new ZonaMap(modelBuilder.Entity<Zona>());
new TipoAlertaMap(modelBuilder.Entity<TipoAlerta>());
new IngresoMap(modelBuilder.Entity<Ingreso>());
new PersonaMap(modelBuilder.Entity<Persona>());
new PersonaVinculoMap(modelBuilder.Entity<PersonaVinculo>());
new PersonaAlertaCargadaMap(modelBuilder.Entity<PersonaAlertaCargada>());
new PersonaAlertaEmitidaMap(modelBuilder.Entity<PersonaAlertaEmitida>());
new TipoUsuarioMap(modelBuilder.Entity<TipoUsuario>());
new HorarioMap(modelBuilder.Entity<Horario>());
new DiaSemanaMap(modelBuilder.Entity<DiaSemana>());
new BoardingPassMap(modelBuilder.Entity<BoardingPass>());
new AerolineaMap(modelBuilder.Entity<Aerolinea>());
new IATAAeropuertoMap(modelBuilder.Entity<IATAAeropuerto>());
new IATAPaisMap(modelBuilder.Entity<IATAPais>());
var mapper = new Npgsql.NpgsqlSnakeCaseNameTranslator();
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
// modify column names
foreach (var property in entity.GetProperties())
{
property.Relational().ColumnName = mapper.TranslateMemberName(property.Relational().ColumnName);
}
// modify table name
entity.Relational().TableName = mapper.TranslateMemberName(entity.Relational().TableName);
// move asp_net tables into schema 'identity'
if (entity.Relational().TableName.StartsWith("asp_net_"))
{
entity.Relational().TableName = entity.Relational().TableName.Replace("asp_net_", string.Empty);
entity.Relational().Schema = "identity";
}
}
}
public void Seed()
{
// this.Database.Migrate();
new Seeder().Seed();
}
} Thanks!!! |
@neumartin This code works for me, assuming that NpgsqlSnakeCaseNameTranslator correctly creates a snake_case name. Can you check that NpgsqlSnakeCaseNameTranslator is generating snake_case names? If not, then please follow up with the owner of that class. Otherwise, please file a new issue with a complete project or code listing that reproduces what you are seeing. |
I make an example here: https://github.com/neumartin/SnakeCaseTest/ But in the example works fine, forget my question. |
The problem was the migrations. |
Previous example not work with keys and indexes, here is modified version that includes it:
|
@AuthorProxy Edit: |
update for efcore3, the Relational() methods have been removed in 469177a, small tweaks in here to make the code compile again property.Relational().ColumnName = ConvertGeneralToSnake(mapper, property.Relational().ColumnName); changes to property.SetColumnName(ConvertGeneralToSnake(mapper, property.GetColumnName())); heres the complete extension public static class ModelBuilderExtensions
{
static readonly Regex _keysRegex = new Regex("^(PK|FK|IX)_", RegexOptions.Compiled);
public static void UseSnakeCaseNames(this 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);
}
}
}
static void ConvertToSnake(INpgsqlNameTranslator mapper, object entity)
{
switch (entity)
{
case IMutableEntityType table:
table.SetTableName(ConvertGeneralToSnake(mapper, table.GetTableName()));
break;
case IMutableProperty property:
property.SetColumnName(ConvertGeneralToSnake(mapper, property.GetColumnName()));
break;
case IMutableKey primaryKey:
primaryKey.SetName(ConvertKeyToSnake(mapper, primaryKey.GetName()));
break;
case IMutableForeignKey foreignKey:
foreignKey.SetConstraintName(ConvertKeyToSnake(mapper, foreignKey.GetConstraintName()));
break;
case IMutableIndex indexKey:
indexKey.SetName(ConvertKeyToSnake(mapper, indexKey.GetName()));
break;
default:
throw new NotImplementedException("Unexpected type was provided to snake case converter");
}
}
static string ConvertKeyToSnake(INpgsqlNameTranslator mapper, string keyName) =>
ConvertGeneralToSnake(mapper, _keysRegex.Replace(keyName, match => match.Value.ToLower()));
static string ConvertGeneralToSnake(INpgsqlNameTranslator mapper, string entityName) =>
mapper.TranslateMemberName(entityName);
} |
For anyone interesting in this, check out EFCore.NamingConventions. If anything is missing or not working for you, please file an issue in that repo. |
I am using EF Core with PostgreSQL/Npgsql. Since PostgreSQL is case sensitive for object names and Properties are proper cased in C# this cause you to use double quotes when writing native sql.
could it be possible to create a pluggable scheme to allow the mapping of object names, similar to what is done when you want to camel case objects to json using CamelCasePropertyNamesContractResolver().
i asked this of the PostgresSQL developers and they think this functionality would be best implemented in EF Core and not in npgsql.
npgsql/efcore.pg#21
The text was updated successfully, but these errors were encountered: