Entity Framework Core: Naming Convention

  • .NET
  • Entity Framework Core
  • .NET

Note: I use the preview version of Entity Framework Core 2.0 (2.0.0-preview1-final). Things may change after the final version is released

Entity Framework migration allows to generate the database schema from the model. This means the name of generated objects has to be inferred from the name of the classes and properties. The default names should be ok for lots of people. However, your DBA may ask you to use a specific a naming convention. For instance, some DBA want the table name to be upper case, or column names to be prefix by the table name.

Entity Framework allows to set the name of a table or a column one by one:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>().ForSqlServerToTable("Blog");
}

However, this code is very borring to write and error prone. Instead of setting the name object by object, you can set it globally by modifying the model. Indeed, the modelBuilder is read/write. This means you can iterate all objects and change their names.

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

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

        // Singularize table name
        // Blogs => Blog
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            // Add NuGet package "Humanizer" to use Singularize()
            entityType.Relational().TableName = entityType.Relational().TableName.Singularize();
        }

        // Prefix column names with table name
        // Id => Blog_Id
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            foreach (var property in entityType.GetProperties())
            {
                property.Relational().ColumnName = entityType.Relational().TableName + "_" + property.Relational().ColumnName;
            }
        }

        // Rename Foreign Key
        // FK_Post_Blog_BlogId => FK_Post_Blog_BlogId_Test
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            foreach (var property in entityType.GetProperties())
            {
                foreach (var fk in entityType.FindForeignKeys(property))
                {
                    fk.Relational().Name = fk.Relational().Name + "_Test";
                }
            }
        }

        // Rename Indices
        // IX_Blog_Url => IX_Blog_Url_Test
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            foreach (var index in entityType.GetIndexes())
            {
                index.Relational().Name = index.Relational().Name + "_Test";
            }
        }
    }
}

Run the following commands in the Package Manager Console

Add-Migration NamingConvention
Update-Database

The previous commands will generate the following schema:

CREATE TABLE [dbo].[Blog] (
    [Blog_BlogId] INT            IDENTITY (1, 1) NOT NULL,
    [Blog_Url]    NVARCHAR (450) NULL,
    CONSTRAINT [PK_Blog] PRIMARY KEY CLUSTERED ([Blog_BlogId] ASC)
);

CREATE UNIQUE NONCLUSTERED INDEX [IX_Blog_Url_Test]
    ON [dbo].[Blog]([Blog_Url] ASC) WHERE ([Blog_Url] IS NOT NULL);

CREATE TABLE [dbo].[Post] (
    [Post_PostId]  INT            IDENTITY (1, 1) NOT NULL,
    [Post_BlogId]  INT            NOT NULL,
    [Post_Content] NVARCHAR (MAX) NULL,
    [Post_Title]   NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_Post] PRIMARY KEY CLUSTERED ([Post_PostId] ASC),
    CONSTRAINT [testFK_Post_Blog_BlogId] FOREIGN KEY ([Post_BlogId]) REFERENCES [dbo].[Blog] ([Blog_BlogId]) ON DELETE CASCADE
);

CREATE NONCLUSTERED INDEX [IX_Post_BlogId_Test]
    ON [dbo].[Post]([Post_BlogId] ASC);

As you can see the name of the generated database objects follow the naming convention defined.

Follow me:
Enjoy this blog?Buy Me A CoffeeDonate with PayPal

Leave a reply