Entity Framework Core RC2 table name pluralization
C#Entity Framework-CorePluralizeTablenameC# Problem Overview
Is there a way to do what this code did in EF Core RC 2?
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
C# Solutions
Solution 1 - C#
There is no convention for this as of EF RC2 build. This is from EF Core team: > In past pre-release of EF Core, the table name for an entity was the > same as the entity class name. In RC2 we now use the name of the DbSet > property. If no DbSet property is defined for the given entity type, > then the entity class name is used.
Now if you want to revert back to the RC1 naming conventions for tables, you have 3 ways to go with:
1. Choosing Singular Names for DbSet Properties:
One way is to singularize your DbSet property names (which I don't like). Say for example you have a Book entity and you want to map to a Book table:
public DbSet<Book> Book { get; set; }
2. Using ToTable() Fluent API:
You can of course always use fluent API to override any convention in place and dictate the table name to whatever you want:
modelBuilder.Entity<Book>().ToTable("Book");
3. Writing a Custom Convention:
Just because EF Core RC2 does not have a convention for this, it doesn't mean we can't write our own. To do so, first we need to create an extension method on ModelBuilder
object:
using Microsoft.EntityFrameworkCore.Metadata.Internal;
public static class ModelBuilderExtensions
{
public static void RemovePluralizingTableNameConvention(this ModelBuilder modelBuilder)
{
foreach (IMutableEntityType entity in modelBuilder.Model.GetEntityTypes())
{
entity.Relational().TableName = entity.DisplayName();
}
}
}
And then we simply call it from the OnModelCreating method on our DbContext object:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.RemovePluralizingTableNameConvention();
}
On Closing:
I don't like plural table names and I like the last option better than the others and went with that. That said, it's my personal opinion and other developers might find any of these 3 ways more favorable than the others and choose to go with that :)
Solution 2 - C#
For EF Core 3.0 and above, use this to set the TableName
property (because entity.Relational()
no longer exist):
public static class ModelBuilderExtensions
{
public static void RemovePluralizingTableNameConvention(this ModelBuilder modelBuilder)
{
foreach (IMutableEntityType entity in modelBuilder.Model.GetEntityTypes())
{
if (entityType.BaseType == null)
{
entity.SetTableName(entity.DisplayName());
}
}
}
}
Solution 3 - C#
The EF Core version doesn't seem to support entity.DisplayName
. This is a working alternative:
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
// Skip shadow types
if (entityType.ClrType == null)
continue;
entityType.Relational().TableName = entityType.ClrType.Name;
}
Solution 4 - C#
This is also an option:
using System.ComponentModel.DataAnnotations.Schema;
[Table("Book")]
public class Book
{...}
although you need to annotate it on each entity
Solution 5 - C#
In Entity Framework NET core v2 you can choose to pluralize or singularize DbSets
and Collections
with a hook.
public class MyDesignTimeServices : IDesignTimeServices
{
public void ConfigureDesignTimeServices(IServiceCollection services)
{
services.AddSingleton<IPluralizer, MyPluralizer>();
}
}
public class MyPluralizer : IPluralizer
{
public string Pluralize(string name)
{
return Inflector.Inflector.Pluralize(name) ?? name;
}
public string Singularize(string name)
{
return Inflector.Inflector.Singularize(name) ?? name;
}
}
See this answer for more information: https://stackoverflow.com/a/47410837/869033
Solution 6 - C#
The EF Core 5 has resolved using a switch "-NoPluralize" while updating the Db Context:
Scaffold-DbContext "..conn str.." Microsoft.EntityFrameworkCore.SqlServer -OutputDir EntityDbContext -Project DoctorsExpress.Domain -Force -NoPluralize
Solution 7 - C#
I use this for EF Core 3.1 to preserve [Table("some_table_name")]
annotation on entity types, although ConventionAnnotation
is an internal class.
static class UseEntityTypeNameForTableNameExtension
{
public static void UseEntityTypeNameForTableName(this ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
var tableNameAnnotation = (ConventionAnnotation)entity.FindAnnotation(RelationalAnnotationNames.TableName);
#pragma warning disable EF1001
var configurationSource = tableNameAnnotation.GetConfigurationSource();
#pragma warning restore EF1001
if (configurationSource != ConfigurationSource.Convention)
{
// Set explicitly using Fluent API or has TableAttribute DataAnnotation
continue;
}
var defaultTableName = entity.GetDefaultTableName();
entity.SetTableName(defaultTableName);
}
}
}
Solution 8 - C#
I went with adding a virtual
public virtual DbSet<TableName> TableName{ get; set; }
public DbSet<TableName> TableNames { get; set; }
TableNames.FirstOrDefault();