69

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>();
}

8 Answers 8

134

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 :)

12
  • 1
    Thank you Morteza. I think that for now I'll just set the table name on the entity. Commented May 28, 2016 at 20:10
  • 3
    @Tančev Saša I tried to call modelBuilder.RemovePluralizingTableNameConvention(); before base.OnModelCreating(builder); and identity tables have OK names
    – zholinho
    Commented Oct 24, 2017 at 8:58
  • 5
    IMutableEntityType doesnt have Relational() method, is it changed? Commented Nov 30, 2018 at 13:16
  • 5
    entity.Relational().TableName = entity.DisplayName(); not work in .net core 3 Commented Nov 30, 2019 at 7:06
  • 7
    You should be able to use entity.SetTableName(entity.DisplayName());
    – hasselmann
    Commented Aug 4, 2020 at 15:38
69

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 (entity.BaseType == null)
            {
                entity.SetTableName(entity.DisplayName());
            }
        }
    }
}
6
  • 2
    If you use this method with an inherited entity, you'll get the error ...Only base type entity types can be mapped to a table.. To work around this, I used the condition if (entity.BaseType == null). Base classes will return null while inherited classes will obviously return the base type.
    – Kramb
    Commented Jun 19, 2020 at 18:50
  • @Métoule : Calling modelBuilder.RemovePluralizingTableNameConvention() causes issues when used in conjunction with entity.ToView("MyView"): The entity is then tagged as a table and not as a view anymore. Commented Dec 7, 2020 at 15:18
  • @Métoule please check possible issues and workarouns for EF Core 5 stackoverflow.com/a/65585664/1769622 Commented Jan 5, 2021 at 21:16
  • 1
    @Creative: entity.SetTableName exists in EF Core 6.
    – Métoule
    Commented Dec 17, 2021 at 13:59
  • 1
    Please edit the if clause, throwed an error. Replace instead: if (entity.BaseType == null).
    – Hagen
    Commented Jan 15, 2023 at 2:21
10

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;
}
1
  • 4
    entity.DisplayName is an extension method in the Microsoft.EntityFrameworkCore.Metadata.Internal namespace (which is actually public, not internal).
    – hgcummings
    Commented Jun 12, 2018 at 14:50
10

This is also an option:

 using System.ComponentModel.DataAnnotations.Schema;

 [Table("Book")]
 public class Book
 {...}

although you need to annotate it on each entity

1
  • I found myself wanting to organize via schema, so I was annotating with this tag on every class anyway. As an Example: [Table("Book", Schema = "library")]
    – Greg
    Commented Sep 3, 2021 at 11:28
6

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
1
  • should be --no-pluralize
    – HydTechie
    Commented Mar 8, 2022 at 17:44
5

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

0

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);
        }
    }
}
-2

I went with adding a virtual

public virtual DbSet<TableName> TableName{ get; set; }
public DbSet<TableName> TableNames { get; set; }

TableNames.FirstOrDefault();
1
  • 1
    Quality username. Low quality answer. You should mention why you went with this approach and how it solves the problem in the description.
    – devklick
    Commented Aug 17, 2022 at 19:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.